diff --git a/.ci/compute_projects.py b/.ci/compute_projects.py index c3cf714ce6c10..8e25fd61d6b32 100644 --- a/.ci/compute_projects.py +++ b/.ci/compute_projects.py @@ -19,6 +19,7 @@ PROJECT_DEPENDENCIES = { "llvm": set(), "clang": {"llvm"}, + "CIR": {"clang", "mlir"}, "bolt": {"clang", "lld", "llvm"}, "clang-tools-extra": {"clang", "llvm"}, "compiler-rt": {"clang", "lld"}, @@ -55,6 +56,7 @@ ".ci": { "llvm", "clang", + "CIR", "lld", "lldb", "bolt", @@ -128,6 +130,7 @@ "lldb": "check-lldb", "llvm": "check-llvm", "clang": "check-clang", + "CIR": "check-clang-cir", "bolt": "check-bolt", "lld": "check-lld", "flang": "check-flang", @@ -247,6 +250,14 @@ def _get_modified_projects(modified_files: list[str]) -> Set[str]: # capacity. if len(path_parts) > 3 and path_parts[:3] == ("llvm", "utils", "gn"): continue + # If the file is in the clang/lib/CIR directory, add the CIR project. + if len(path_parts) > 3 and ( + path_parts[:3] == ("clang", "lib", "CIR") + or path_parts[:3] == ("clang", "test", "CIR") + or path_parts[:4] == ("clang", "include", "clang", "CIR") + ): + modified_projects.add("CIR") + # Fall through to add clang. modified_projects.add(pathlib.Path(modified_file).parts[0]) return modified_projects @@ -267,6 +278,13 @@ def get_env_variables(modified_files: list[str], platform: str) -> Set[str]: runtimes_check_targets_needs_reconfig = _compute_project_check_targets( runtimes_to_test_needs_reconfig ) + + # CIR is used as a pseudo-project in this script. It is built as part of the + # clang build, but it requires an explicit option to enable. We set that + # option here, and remove it from the projects_to_build list. + enable_cir = "ON" if "CIR" in projects_to_build else "OFF" + projects_to_build.discard("CIR") + # We use a semicolon to separate the projects/runtimes as they get passed # to the CMake invocation and thus we need to use the CMake list separator # (;). We use spaces to separate the check targets as they end up getting @@ -279,6 +297,7 @@ def get_env_variables(modified_files: list[str], platform: str) -> Set[str]: "runtimes_check_targets_needs_reconfig": " ".join( sorted(runtimes_check_targets_needs_reconfig) ), + "enable_cir": enable_cir, } diff --git a/.ci/compute_projects_test.py b/.ci/compute_projects_test.py index 6299931e1ec34..732514c96f5a6 100644 --- a/.ci/compute_projects_test.py +++ b/.ci/compute_projects_test.py @@ -104,6 +104,10 @@ def test_clang(self): env_variables["runtimes_check_targets_needs_reconfig"], "check-cxx check-cxxabi check-unwind", ) + self.assertEqual( + env_variables["enable_cir"], + "OFF", + ) def test_clang_windows(self): env_variables = compute_projects.get_env_variables( @@ -126,6 +130,32 @@ def test_clang_windows(self): env_variables["runtimes_check_targets_needs_reconfig"], "check-cxx check-cxxabi check-unwind", ) + self.assertEqual(env_variables["enable_cir"], "OFF") + + def test_cir(self): + env_variables = compute_projects.get_env_variables( + ["clang/lib/CIR/CMakeLists.txt"], "Linux" + ) + self.assertEqual( + env_variables["projects_to_build"], + "clang;clang-tools-extra;lld;llvm;mlir", + ) + self.assertEqual( + env_variables["project_check_targets"], + "check-clang check-clang-cir check-clang-tools", + ) + self.assertEqual( + env_variables["runtimes_to_build"], "compiler-rt;libcxx;libcxxabi;libunwind" + ) + self.assertEqual( + env_variables["runtimes_check_targets"], + "check-compiler-rt", + ) + self.assertEqual( + env_variables["runtimes_check_targets_needs_reconfig"], + "check-cxx check-cxxabi check-unwind", + ) + self.assertEqual(env_variables["enable_cir"], "ON") def test_bolt(self): env_variables = compute_projects.get_env_variables( @@ -158,6 +188,7 @@ def test_mlir(self): self.assertEqual(env_variables["runtimes_to_build"], "") self.assertEqual(env_variables["runtimes_check_targets"], "") self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "") + self.assertEqual(env_variables["enable_cir"], "OFF") def test_flang(self): env_variables = compute_projects.get_env_variables( @@ -168,6 +199,7 @@ def test_flang(self): self.assertEqual(env_variables["runtimes_to_build"], "") self.assertEqual(env_variables["runtimes_check_targets"], "") self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "") + self.assertEqual(env_variables["enable_cir"], "OFF") def test_invalid_subproject(self): env_variables = compute_projects.get_env_variables( @@ -237,7 +269,7 @@ def test_ci(self): ) self.assertEqual( env_variables["project_check_targets"], - "check-bolt check-clang check-clang-tools check-flang check-lld check-lldb check-llvm check-mlir check-polly", + "check-bolt check-clang check-clang-cir check-clang-tools check-flang check-lld check-lldb check-llvm check-mlir check-polly", ) self.assertEqual( env_variables["runtimes_to_build"], diff --git a/.ci/monolithic-linux.sh b/.ci/monolithic-linux.sh index 8d1faab13986c..6db24d894eb73 100755 --- a/.ci/monolithic-linux.sh +++ b/.ci/monolithic-linux.sh @@ -21,12 +21,7 @@ BUILD_DIR="${BUILD_DIR:=${MONOREPO_ROOT}/build}" INSTALL_DIR="${BUILD_DIR}/install" rm -rf "${BUILD_DIR}" -ccache --zero-stats - -if [[ -n "${CLEAR_CACHE:-}" ]]; then - echo "clearing cache" - ccache --clear -fi +sccache --zero-stats mkdir -p artifacts/reproducers @@ -36,7 +31,7 @@ export CLANG_CRASH_DIAGNOSTICS_DIR=`realpath artifacts/reproducers` function at-exit { retcode=$? - ccache --print-stats > artifacts/ccache_stats.txt + sccache --show-stats > artifacts/sccache_stats.txt cp "${BUILD_DIR}"/.ninja_log artifacts/.ninja_log cp "${BUILD_DIR}"/test-results.*.xml artifacts/ || : @@ -53,6 +48,7 @@ targets="${2}" runtimes="${3}" runtime_targets="${4}" runtime_targets_needs_reconfig="${5}" +enable_cir="${6}" lit_args="-v --xunit-xml-output ${BUILD_DIR}/test-results.xml --use-unique-output-file-name --timeout=1200 --time-tests" @@ -72,13 +68,15 @@ cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \ -G Ninja \ -D CMAKE_PREFIX_PATH="${HOME}/.local" \ -D CMAKE_BUILD_TYPE=Release \ + -D CLANG_ENABLE_CIR=${enable_cir} \ -D LLVM_ENABLE_ASSERTIONS=ON \ -D LLVM_BUILD_EXAMPLES=ON \ -D COMPILER_RT_BUILD_LIBFUZZER=OFF \ -D LLVM_LIT_ARGS="${lit_args}" \ -D LLVM_ENABLE_LLD=ON \ -D CMAKE_CXX_FLAGS=-gmlt \ - -D LLVM_CCACHE_BUILD=ON \ + -D CMAKE_C_COMPILER_LAUNCHER=sccache \ + -D CMAKE_CXX_COMPILER_LAUNCHER=sccache \ -D LIBCXX_CXX_ABI=libcxxabi \ -D MLIR_ENABLE_BINDINGS_PYTHON=ON \ -D LLDB_ENABLE_PYTHON=ON \ diff --git a/.ci/monolithic-windows.sh b/.ci/monolithic-windows.sh index 176350fac604c..50a741677d734 100755 --- a/.ci/monolithic-windows.sh +++ b/.ci/monolithic-windows.sh @@ -21,11 +21,6 @@ BUILD_DIR="${BUILD_DIR:=${MONOREPO_ROOT}/build}" rm -rf "${BUILD_DIR}" -if [[ -n "${CLEAR_CACHE:-}" ]]; then - echo "clearing sccache" - rm -rf "$SCCACHE_DIR" -fi - sccache --zero-stats function at-exit { retcode=$? diff --git a/.github/new-prs-labeler.yml b/.github/new-prs-labeler.yml index b05e9c6c56ed0..8e0fa8d42d735 100644 --- a/.github/new-prs-labeler.yml +++ b/.github/new-prs-labeler.yml @@ -48,6 +48,9 @@ flang:frontend: - flang/Evaluate/**/* - flang/Semantics/**/* +libclc: + - libclc/** + HLSL: - clang/*HLSL*/**/* - clang/**/*HLSL* @@ -717,6 +720,8 @@ mlgo: - llvm/lib/Analysis/IR2Vec.cpp - llvm/lib/Analysis/models/** - llvm/test/Analysis/IR2Vec/** + - llvm/tools/llvm-ir2vec/** + - llvm/docs/CommandGuide/llvm-ir2vec.rst tools:llvm-exegesis: - llvm/tools/llvm-exegesis/** diff --git a/.github/workflows/build-ci-container-windows.yml b/.github/workflows/build-ci-container-windows.yml index 59079f057d021..f76c69f29fb30 100644 --- a/.github/workflows/build-ci-container-windows.yml +++ b/.github/workflows/build-ci-container-windows.yml @@ -11,8 +11,6 @@ on: - .github/workflows/build-ci-container-windows.yml - '.github/workflows/containers/github-action-ci-windows/**' pull_request: - branches: - - main paths: - .github/workflows/build-ci-container-windows.yml - '.github/workflows/containers/github-action-ci-windows/**' diff --git a/.github/workflows/build-ci-container.yml b/.github/workflows/build-ci-container.yml index 3159aae32ca51..7f01264af8534 100644 --- a/.github/workflows/build-ci-container.yml +++ b/.github/workflows/build-ci-container.yml @@ -11,8 +11,6 @@ on: - .github/workflows/build-ci-container.yml - '.github/workflows/containers/github-action-ci/**' pull_request: - branches: - - main paths: - .github/workflows/build-ci-container.yml - '.github/workflows/containers/github-action-ci/**' diff --git a/.github/workflows/containers/github-action-ci/Dockerfile b/.github/workflows/containers/github-action-ci/Dockerfile index efe08ebc221c5..69c71f638e2ac 100644 --- a/.github/workflows/containers/github-action-ci/Dockerfile +++ b/.github/workflows/containers/github-action-ci/Dockerfile @@ -63,11 +63,21 @@ RUN apt-get update && \ python3-pip \ ccache \ file \ - tzdata \ - sccache && \ + tzdata && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* +# We need sccache for caching. We cannot use the apt repository version because +# it is too old and has bugs related to features we require (particularly GCS +# caching), so we manually install it here. +# TODO(boomanaiden154): We should return to installing this from the apt +# repository once a version containing the necessary bug fixes is available. +RUN curl -L 'https://github.com/mozilla/sccache/releases/download/v0.10.0/sccache-v0.10.0-x86_64-unknown-linux-musl.tar.gz' > /tmp/sccache.tar.gz && \ + echo "1fbb35e135660d04a2d5e42b59c7874d39b3deb17de56330b25b713ec59f849b /tmp/sccache.tar.gz" | sha256sum -c && \ + tar xzf /tmp/sccache.tar.gz -O --wildcards '*/sccache' > '/usr/local/bin/sccache' && \ + rm /tmp/sccache.tar.gz && \ + chmod +x /usr/local/bin/sccache + ENV LLVM_SYSROOT=$LLVM_SYSROOT ENV PATH=${LLVM_SYSROOT}/bin:${PATH} diff --git a/.github/workflows/premerge.yaml b/.github/workflows/premerge.yaml index ff63355222065..c51325e2f0d45 100644 --- a/.github/workflows/premerge.yaml +++ b/.github/workflows/premerge.yaml @@ -34,10 +34,6 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 2 - - name: Setup ccache - uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17 - with: - max-size: "2000M" - name: Build and Test # Mark the job as a success even if the step fails so that people do # not get notified while the new premerge pipeline is in an @@ -61,7 +57,14 @@ jobs: export CC=/opt/llvm/bin/clang export CXX=/opt/llvm/bin/clang++ - ./.ci/monolithic-linux.sh "${projects_to_build}" "${project_check_targets}" "${runtimes_to_build}" "${runtimes_check_targets}" "${runtimes_check_targets_needs_reconfig}" + # This environment variable is passes into the container through the + # runner pod definition. This differs between our two clusters which + # why we do not hardcode it. + export SCCACHE_GCS_BUCKET=$CACHE_GCS_BUCKET + export SCCACHE_GCS_RW_MODE=READ_WRITE + sccache --start-server + + ./.ci/monolithic-linux.sh "${projects_to_build}" "${project_check_targets}" "${runtimes_to_build}" "${runtimes_check_targets}" "${runtimes_check_targets_needs_reconfig}" "${enable_cir}" - name: Upload Artifacts if: '!cancelled()' uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 @@ -85,11 +88,6 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 2 - - name: Setup ccache - uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17 - with: - variant: "sccache" - max-size: "2000M" - name: Compute Projects id: vars run: | @@ -112,7 +110,7 @@ jobs: shell: cmd run: | call C:\\BuildTools\\Common7\\Tools\\VsDevCmd.bat -arch=amd64 -host_arch=amd64 - bash .ci/monolithic-windows.sh "${{ steps.vars.outputs.windows-projects }}" "${{ steps.vars.outputs.windows-check-targets }}" + bash -c "export SCCACHE_GCS_BUCKET=$CACHE_GCS_BUCKET; export SCCACHE_GCS_RW_MODE=READ_WRITE; sccache --start-server; .ci/monolithic-windows.sh \"${{ steps.vars.outputs.windows-projects }}\" \"${{ steps.vars.outputs.windows-check-targets }}\"" - name: Upload Artifacts if: '!cancelled()' uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 diff --git a/bolt/utils/nfc-check-setup.py b/bolt/utils/nfc-check-setup.py index 275ac7b886d00..d8666e2158499 100755 --- a/bolt/utils/nfc-check-setup.py +++ b/bolt/utils/nfc-check-setup.py @@ -7,6 +7,8 @@ import sys import textwrap +msg_prefix = "\n> NFC-Mode:" + def get_relevant_bolt_changes(dir: str) -> str: # Return a list of bolt source changes that are relevant to testing. all_changes = subprocess.run( @@ -42,14 +44,32 @@ def get_git_ref_or_rev(dir: str) -> str: cmd_rev = "git rev-parse --short HEAD" return subprocess.check_output(shlex.split(cmd_rev), cwd=dir, text=True).strip() +def switch_back( + switch_back: bool, stash: bool, source_dir: str, old_ref: str, new_ref: str +): + # Switch back to the current revision if needed and inform the user of where + # the HEAD is. Must be called after checking out the previous commit on all + # exit paths. + if switch_back: + print(f"{msg_prefix} Switching back to current revision..") + if stash: + subprocess.run(shlex.split("git stash pop"), cwd=source_dir) + subprocess.run(shlex.split(f"git checkout {old_ref}"), cwd=source_dir) + else: + print( + f"The repository {source_dir} has been switched from {old_ref} " + f"to {new_ref}. Local changes were stashed. Switch back using\n\t" + f"git checkout {old_ref}\n" + ) def main(): parser = argparse.ArgumentParser( description=textwrap.dedent( """ - This script builds two versions of BOLT (with the current and - previous revision) and sets up symlink for llvm-bolt-wrapper. - Passes the options through to llvm-bolt-wrapper. + This script builds two versions of BOLT: + llvm-bolt.new, using the current revision, and llvm-bolt.old using + the previous revision. These can be used to check whether the + current revision changes BOLT's functional behavior. """ ) ) @@ -59,6 +79,12 @@ def main(): default=os.getcwd(), help="Path to BOLT build directory, default is current " "directory", ) + parser.add_argument( + "--create-wrapper", + default=False, + action="store_true", + help="Sets up llvm-bolt as a symlink to llvm-bolt-wrapper. Passes the options through to llvm-bolt-wrapper.", + ) parser.add_argument( "--check-bolt-sources", default=False, @@ -76,28 +102,42 @@ def main(): default="HEAD^", help="Revision to checkout to compare vs HEAD", ) + + # When creating a wrapper, pass any unknown arguments to it. Otherwise, die. args, wrapper_args = parser.parse_known_args() - bolt_path = f"{args.build_dir}/bin/llvm-bolt" + if not args.create_wrapper and len(wrapper_args) > 0: + parser.parse_args() + # Find the repo directory. source_dir = None - # find the repo directory - with open(f"{args.build_dir}/CMakeCache.txt") as f: - for line in f: - m = re.match(r"LLVM_SOURCE_DIR:STATIC=(.*)", line) - if m: - source_dir = m.groups()[0] - if not source_dir: - sys.exit("Source directory is not found") - - script_dir = os.path.dirname(os.path.abspath(__file__)) - wrapper_path = f"{script_dir}/llvm-bolt-wrapper.py" - # build the current commit + try: + CMCacheFilename = f"{args.build_dir}/CMakeCache.txt" + with open(CMCacheFilename) as f: + for line in f: + m = re.match(r"LLVM_SOURCE_DIR:STATIC=(.*)", line) + if m: + source_dir = m.groups()[0] + if not source_dir: + raise Exception(f"Source directory not found: '{CMCacheFilename}'") + except Exception as e: + sys.exit(e) + + # Clean the previous llvm-bolt if it exists. + bolt_path = f"{args.build_dir}/bin/llvm-bolt" + if os.path.exists(bolt_path): + os.remove(bolt_path) + + # Build the current commit. + print(f"{msg_prefix} Building current revision..") subprocess.run( shlex.split("cmake --build . --target llvm-bolt"), cwd=args.build_dir ) - # rename llvm-bolt + + if not os.path.exists(bolt_path): + sys.exit(f"Failed to build the current revision: '{bolt_path}'") + + # Rename llvm-bolt and memorize the old hash for logging. os.replace(bolt_path, f"{bolt_path}.new") - # memorize the old hash for logging old_ref = get_git_ref_or_rev(source_dir) if args.check_bolt_sources: @@ -110,7 +150,7 @@ def main(): print(f"BOLT source changes were found:\n{file_changes}") open(marker, "a").close() - # determine whether a stash is needed + # Determine whether a stash is needed. stash = subprocess.run( shlex.split("git status --porcelain"), cwd=source_dir, @@ -119,42 +159,59 @@ def main(): text=True, ).stdout if stash: - # save local changes before checkout + # Save local changes before checkout. subprocess.run(shlex.split("git stash push -u"), cwd=source_dir) - # check out the previous/cmp commit + + # Check out the previous/cmp commit and get its commit hash for logging. subprocess.run(shlex.split(f"git checkout -f {args.cmp_rev}"), cwd=source_dir) - # get the parent commit hash for logging new_ref = get_git_ref_or_rev(source_dir) - # build the previous commit + + # Build the previous commit. + print(f"{msg_prefix} Building previous revision..") subprocess.run( shlex.split("cmake --build . --target llvm-bolt"), cwd=args.build_dir ) - # rename llvm-bolt + + # Rename llvm-bolt. + if not os.path.exists(bolt_path): + print(f"Failed to build the previous revision: '{bolt_path}'") + switch_back(args.switch_back, stash, source_dir, old_ref, new_ref) + sys.exit(1) os.replace(bolt_path, f"{bolt_path}.old") - # set up llvm-bolt-wrapper.ini - ini = subprocess.check_output( - shlex.split(f"{wrapper_path} {bolt_path}.old {bolt_path}.new") + wrapper_args, - text=True, + + # Symlink llvm-bolt-wrapper + if args.create_wrapper: + print(f"{msg_prefix} Creating llvm-bolt wrapper..") + script_dir = os.path.dirname(os.path.abspath(__file__)) + wrapper_path = f"{script_dir}/llvm-bolt-wrapper.py" + try: + # Set up llvm-bolt-wrapper.ini + ini = subprocess.check_output( + shlex.split(f"{wrapper_path} {bolt_path}.old {bolt_path}.new") + + wrapper_args, + text=True, + ) + with open(f"{args.build_dir}/bin/llvm-bolt-wrapper.ini", "w") as f: + f.write(ini) + os.symlink(wrapper_path, bolt_path) + except Exception as e: + print("Failed to create a wrapper:\n" + str(e)) + switch_back(args.switch_back, stash, source_dir, old_ref, new_ref) + sys.exit(1) + + switch_back(args.switch_back, stash, source_dir, old_ref, new_ref) + + print( + f"{msg_prefix} Completed!\nBuild directory {args.build_dir} is ready for" + " NFC-Mode comparison between the two revisions." ) - with open(f"{args.build_dir}/bin/llvm-bolt-wrapper.ini", "w") as f: - f.write(ini) - # symlink llvm-bolt-wrapper - os.symlink(wrapper_path, bolt_path) - if args.switch_back: - if stash: - subprocess.run(shlex.split("git stash pop"), cwd=source_dir) - subprocess.run(shlex.split(f"git checkout {old_ref}"), cwd=source_dir) - else: + + if args.create_wrapper: print( - f"The repository {source_dir} has been switched from {old_ref} " - f"to {new_ref}. Local changes were stashed. Switch back using\n\t" - f"git checkout {old_ref}\n" + "Can run BOLT tests using:\n" + "\tbin/llvm-lit -sv tools/bolt/test\nor\n" + "\tbin/llvm-lit -sv tools/bolttests" ) - print( - f"Build directory {args.build_dir} is ready to run BOLT tests, e.g.\n" - "\tbin/llvm-lit -sv tools/bolt/test\nor\n" - "\tbin/llvm-lit -sv tools/bolttests" - ) if __name__ == "__main__": diff --git a/clang-tools-extra/README.txt b/clang-tools-extra/README.txt index 6891e4078997f..1195db9b468dd 100644 --- a/clang-tools-extra/README.txt +++ b/clang-tools-extra/README.txt @@ -8,12 +8,13 @@ Clang frontend. These tools are kept in a separate "extra" repository to allow lighter weight checkouts of the core Clang codebase. All discussion regarding Clang, Clang-based tools, and code in this repository -should be held using the standard Clang forum: +should be held using the standard Clang forums: https://discourse.llvm.org/c/clang + https://discourse.llvm.org/c/clang/clang-tidy/71 + https://discourse.llvm.org/c/clang/clangd/34 -Code review for this tree should take place on the standard Clang patch and -commit lists: - http://lists.llvm.org/mailman/listinfo/cfe-commits +Code review for this tree should take place on Github: + https://github.com/llvm/llvm-project/pulls?q=label%3Aclang-tools-extra If you find a bug in these tools, please file it in the LLVM bug tracker: https://github.com/llvm/llvm-project/issues/ diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp b/clang-tools-extra/clang-doc/JSONGenerator.cpp index 6fdc7196e9095..cc4c68346ec53 100644 --- a/clang-tools-extra/clang-doc/JSONGenerator.cpp +++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp @@ -45,7 +45,7 @@ static auto SerializeReferenceLambda = [](const auto &Ref, Object &Object) { static json::Object serializeLocation(const Location &Loc, - const std::optional &RepositoryUrl) { + const std::optional RepositoryUrl) { Object LocationObj = Object(); LocationObj["LineNumber"] = Loc.StartLineNumber; LocationObj["Filename"] = Loc.Filename; @@ -169,7 +169,7 @@ static json::Value serializeComment(const CommentInfo &I) { static void serializeCommonAttributes(const Info &I, json::Object &Obj, - const std::optional &RepositoryUrl) { + const std::optional RepositoryUrl) { Obj["Name"] = I.Name; Obj["USR"] = toHex(toStringRef(I.USR)); @@ -211,9 +211,9 @@ static void serializeReference(const Reference &Ref, Object &ReferenceObj) { // differently. Only enums, records, and typedefs are handled here. static void serializeCommonChildren(const ScopeChildren &Children, json::Object &Obj, - const std::optional &RepositoryUrl) { - static auto SerializeInfo = [&RepositoryUrl](const auto &Info, - Object &Object) { + const std::optional RepositoryUrl) { + static auto SerializeInfo = [RepositoryUrl](const auto &Info, + Object &Object) { serializeInfo(Info, Object, RepositoryUrl); }; @@ -304,7 +304,7 @@ static void serializeInfo(const FieldTypeInfo &I, Object &Obj) { } static void serializeInfo(const FunctionInfo &F, json::Object &Obj, - const std::optional &RepositoryURL) { + const std::optional RepositoryURL) { serializeCommonAttributes(F, Obj, RepositoryURL); Obj["IsStatic"] = F.IsStatic; @@ -459,7 +459,7 @@ static void serializeInfo(const RecordInfo &I, json::Object &Obj, } static void serializeInfo(const VarInfo &I, json::Object &Obj, - const std::optional &RepositoryUrl) { + const std::optional RepositoryUrl) { serializeCommonAttributes(I, Obj, RepositoryUrl); Obj["IsStatic"] = I.IsStatic; auto TypeObj = Object(); @@ -468,15 +468,15 @@ static void serializeInfo(const VarInfo &I, json::Object &Obj, } static void serializeInfo(const NamespaceInfo &I, json::Object &Obj, - const std::optional &RepositoryUrl) { + const std::optional RepositoryUrl) { serializeCommonAttributes(I, Obj, RepositoryUrl); if (!I.Children.Namespaces.empty()) serializeArray(I.Children.Namespaces, Obj, "Namespaces", SerializeReferenceLambda); - static auto SerializeInfo = [&RepositoryUrl](const auto &Info, - Object &Object) { + static auto SerializeInfo = [RepositoryUrl](const auto &Info, + Object &Object) { serializeInfo(Info, Object, RepositoryUrl); }; diff --git a/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp index 3c3024d538785..4b495e3877000 100644 --- a/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp @@ -49,7 +49,7 @@ static Matcher loopEndingStmt(Matcher Internal) { } /// Return whether `Var` was changed in `LoopStmt`. -static bool isChanged(const Stmt *LoopStmt, const VarDecl *Var, +static bool isChanged(const Stmt *LoopStmt, const ValueDecl *Var, ASTContext *Context) { if (const auto *ForLoop = dyn_cast(LoopStmt)) return (ForLoop->getInc() && @@ -64,24 +64,35 @@ static bool isChanged(const Stmt *LoopStmt, const VarDecl *Var, return ExprMutationAnalyzer(*LoopStmt, *Context).isMutated(Var); } +static bool isVarPossiblyChanged(const Decl *Func, const Stmt *LoopStmt, + const ValueDecl *VD, ASTContext *Context) { + const VarDecl *Var = nullptr; + if (const auto *VarD = dyn_cast(VD)) { + Var = VarD; + } else if (const auto *BD = dyn_cast(VD)) { + if (const auto *DD = dyn_cast(BD->getDecomposedDecl())) + Var = DD; + } + + if (!Var) + return false; + + if (!Var->isLocalVarDeclOrParm() || Var->getType().isVolatileQualified()) + return true; + + if (!VD->getType().getTypePtr()->isIntegerType()) + return true; + + return hasPtrOrReferenceInFunc(Func, VD) || isChanged(LoopStmt, VD, Context); + // FIXME: Track references. +} + /// Return whether `Cond` is a variable that is possibly changed in `LoopStmt`. static bool isVarThatIsPossiblyChanged(const Decl *Func, const Stmt *LoopStmt, const Stmt *Cond, ASTContext *Context) { if (const auto *DRE = dyn_cast(Cond)) { - if (const auto *Var = dyn_cast(DRE->getDecl())) { - if (!Var->isLocalVarDeclOrParm()) - return true; - - if (Var->getType().isVolatileQualified()) - return true; - - if (!Var->getType().getTypePtr()->isIntegerType()) - return true; - - return hasPtrOrReferenceInFunc(Func, Var) || - isChanged(LoopStmt, Var, Context); - // FIXME: Track references. - } + if (const auto *VD = dyn_cast(DRE->getDecl())) + return isVarPossiblyChanged(Func, LoopStmt, VD, Context); } else if (isa(Cond)) { // FIXME: Handle MemberExpr. @@ -123,6 +134,10 @@ static std::string getCondVarNames(const Stmt *Cond) { if (const auto *DRE = dyn_cast(Cond)) { if (const auto *Var = dyn_cast(DRE->getDecl())) return std::string(Var->getName()); + + if (const auto *BD = dyn_cast(DRE->getDecl())) { + return std::string(BD->getName()); + } } std::string Result; @@ -214,10 +229,17 @@ static bool overlap(ArrayRef SCC, /// returns true iff `Cond` involves at least one static local variable. static bool hasStaticLocalVariable(const Stmt *Cond) { - if (const auto *DRE = dyn_cast(Cond)) + if (const auto *DRE = dyn_cast(Cond)) { if (const auto *VD = dyn_cast(DRE->getDecl())) if (VD->isStaticLocal()) return true; + + if (const auto *BD = dyn_cast(DRE->getDecl())) + if (const auto *DD = dyn_cast(BD->getDecomposedDecl())) + if (DD->isStaticLocal()) + return true; + } + for (const Stmt *Child : Cond->children()) if (Child && hasStaticLocalVariable(Child)) return true; diff --git a/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp index 33642c407a3a9..bfa2ab51a6d03 100644 --- a/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp @@ -45,7 +45,7 @@ static void replaceMoveWithForward(const UnresolvedLookupExpr *Callee, // We still conservatively put a "std::" in front of the forward because // we don't know whether the code also had a "using std::forward;". Diag << FixItHint::CreateReplacement(CallRange, "std::" + ForwardName); - } else if (const NamespaceDecl *Namespace = NNS->getAsNamespace()) { + } else if (const NamespaceBaseDecl *Namespace = NNS->getAsNamespace()) { if (Namespace->getName() == "std") { if (!NNS->getPrefix()) { // Called as "std::move". diff --git a/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.cpp b/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.cpp index 2dfaca19a8981..86992cd8a141b 100644 --- a/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.cpp @@ -36,7 +36,8 @@ void UnusedAliasDeclsCheck::check(const MatchFinder::MatchResult &Result) { if (const auto *NestedName = Result.Nodes.getNodeAs("nns")) { - if (const auto *AliasDecl = NestedName->getAsNamespaceAlias()) { + if (const auto *AliasDecl = dyn_cast_if_present( + NestedName->getAsNamespace())) { FoundDecls[AliasDecl] = CharSourceRange(); } } diff --git a/clang-tools-extra/clang-tidy/utils/Aliasing.cpp b/clang-tools-extra/clang-tidy/utils/Aliasing.cpp index 2facf0625605e..cbe4873b5c022 100644 --- a/clang-tools-extra/clang-tidy/utils/Aliasing.cpp +++ b/clang-tools-extra/clang-tidy/utils/Aliasing.cpp @@ -14,14 +14,14 @@ namespace clang::tidy::utils { /// Return whether \p S is a reference to the declaration of \p Var. -static bool isAccessForVar(const Stmt *S, const VarDecl *Var) { +static bool isAccessForVar(const Stmt *S, const ValueDecl *Var) { if (const auto *DRE = dyn_cast(S)) return DRE->getDecl() == Var; return false; } -static bool capturesByRef(const CXXRecordDecl *RD, const VarDecl *Var) { +static bool capturesByRef(const CXXRecordDecl *RD, const ValueDecl *Var) { return llvm::any_of(RD->captures(), [Var](const LambdaCapture &C) { return C.capturesVariable() && C.getCaptureKind() == LCK_ByRef && C.getCapturedVar() == Var; @@ -29,9 +29,9 @@ static bool capturesByRef(const CXXRecordDecl *RD, const VarDecl *Var) { } /// Return whether \p Var has a pointer or reference in \p S. -static bool isPtrOrReferenceForVar(const Stmt *S, const VarDecl *Var) { +static bool isPtrOrReferenceForVar(const Stmt *S, const ValueDecl *Var) { // Treat block capture by reference as a form of taking a reference. - if (Var->isEscapingByref()) + if (const auto *VD = dyn_cast(Var); VD && VD->isEscapingByref()) return true; if (const auto *DS = dyn_cast(S)) { @@ -61,7 +61,7 @@ static bool isPtrOrReferenceForVar(const Stmt *S, const VarDecl *Var) { } /// Return whether \p Var has a pointer or reference in \p S. -static bool hasPtrOrReferenceInStmt(const Stmt *S, const VarDecl *Var) { +static bool hasPtrOrReferenceInStmt(const Stmt *S, const ValueDecl *Var) { if (isPtrOrReferenceForVar(S, Var)) return true; @@ -77,7 +77,7 @@ static bool hasPtrOrReferenceInStmt(const Stmt *S, const VarDecl *Var) { } static bool refersToEnclosingLambdaCaptureByRef(const Decl *Func, - const VarDecl *Var) { + const ValueDecl *Var) { const auto *MD = dyn_cast(Func); if (!MD) return false; @@ -89,7 +89,7 @@ static bool refersToEnclosingLambdaCaptureByRef(const Decl *Func, return capturesByRef(RD, Var); } -bool hasPtrOrReferenceInFunc(const Decl *Func, const VarDecl *Var) { +bool hasPtrOrReferenceInFunc(const Decl *Func, const ValueDecl *Var) { return hasPtrOrReferenceInStmt(Func->getBody(), Var) || refersToEnclosingLambdaCaptureByRef(Func, Var); } diff --git a/clang-tools-extra/clang-tidy/utils/Aliasing.h b/clang-tools-extra/clang-tidy/utils/Aliasing.h index 7dad16fc57f1e..6c0763b766805 100644 --- a/clang-tools-extra/clang-tidy/utils/Aliasing.h +++ b/clang-tools-extra/clang-tidy/utils/Aliasing.h @@ -25,7 +25,7 @@ namespace clang::tidy::utils { /// For `f()` and `n` the function returns ``true`` because `p` is a /// pointer to `n` created in `f()`. -bool hasPtrOrReferenceInFunc(const Decl *Func, const VarDecl *Var); +bool hasPtrOrReferenceInFunc(const Decl *Func, const ValueDecl *Var); } // namespace clang::tidy::utils diff --git a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp index 6cf38ddf3d914..dd28806e008ed 100644 --- a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp +++ b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp @@ -282,7 +282,8 @@ class RenamerClangTidyVisitor bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc Loc) { if (const NestedNameSpecifier *Spec = Loc.getNestedNameSpecifier()) { - if (const NamespaceDecl *Decl = Spec->getAsNamespace()) + if (const auto *Decl = + dyn_cast_if_present(Spec->getAsNamespace())) Check->addUsage(Decl, Loc.getLocalSourceRange(), SM); } diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp index e274236527817..f2631e5abb6a3 100644 --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -666,12 +666,14 @@ std::string getQualification(ASTContext &Context, return getQualification( Context, DestContext, ND->getDeclContext(), [&](NestedNameSpecifier *NNS) { - if (NNS->getKind() != NestedNameSpecifier::Namespace) + const NamespaceDecl *NS = + dyn_cast_if_present(NNS->getAsNamespace()); + if (!NS) return false; - const auto *CanonNSD = NNS->getAsNamespace()->getCanonicalDecl(); + NS = NS->getCanonicalDecl(); return llvm::any_of(VisibleNamespaceDecls, - [CanonNSD](const NamespaceDecl *NSD) { - return NSD->getCanonicalDecl() == CanonNSD; + [NS](const NamespaceDecl *NSD) { + return NSD->getCanonicalDecl() == NS; }); }); } diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index d5907e3143bf6..184c3c962f063 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -1470,7 +1470,6 @@ bool allowIndex(CodeCompletionContext &CC) { switch (NameSpec->getKind()) { case NestedNameSpecifier::Global: case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: return true; case NestedNameSpecifier::Super: case NestedNameSpecifier::TypeSpec: diff --git a/clang-tools-extra/clangd/DumpAST.cpp b/clang-tools-extra/clangd/DumpAST.cpp index 8f24477ecd3de..c6075e75e9a6b 100644 --- a/clang-tools-extra/clangd/DumpAST.cpp +++ b/clang-tools-extra/clangd/DumpAST.cpp @@ -158,7 +158,6 @@ class DumpVisitor : public RecursiveASTVisitor { NNS_KIND(TypeSpec); NNS_KIND(Global); NNS_KIND(Super); - NNS_KIND(NamespaceAlias); #undef NNS_KIND } llvm_unreachable("Unhandled SpecifierKind enum"); @@ -281,8 +280,6 @@ class DumpVisitor : public RecursiveASTVisitor { return NNS.getAsIdentifier()->getName().str() + "::"; case NestedNameSpecifier::Namespace: return NNS.getAsNamespace()->getNameAsString() + "::"; - case NestedNameSpecifier::NamespaceAlias: - return NNS.getAsNamespaceAlias()->getNameAsString() + "::"; default: return ""; } diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp index 91fd3b0f8567b..b1089577ba819 100644 --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -491,9 +491,6 @@ struct TargetFinder { case NestedNameSpecifier::Namespace: add(NNS->getAsNamespace(), Flags); return; - case NestedNameSpecifier::NamespaceAlias: - add(NNS->getAsNamespaceAlias(), Flags); - return; case NestedNameSpecifier::Identifier: if (Resolver) { add(Resolver->resolveNestedNameSpecifierToType(NNS), Flags); diff --git a/clang-tools-extra/clangd/IncludeFixer.cpp b/clang-tools-extra/clangd/IncludeFixer.cpp index 4ff021c4c390a..50bc2bd7ccb94 100644 --- a/clang-tools-extra/clangd/IncludeFixer.cpp +++ b/clang-tools-extra/clangd/IncludeFixer.cpp @@ -403,25 +403,27 @@ std::optional extractUnresolvedNameCheaply( if (auto *Nested = SS->getScopeRep()) { if (Nested->getKind() == NestedNameSpecifier::Global) { Result.ResolvedScope = ""; - } else if (const auto *NS = Nested->getAsNamespace()) { - std::string SpecifiedNS = printNamespaceScope(*NS); - std::optional Spelling = getSpelledSpecifier(*SS, SM); - - // Check the specifier spelled in the source. - // If the resolved scope doesn't end with the spelled scope, the - // resolved scope may come from a sema typo correction. For example, - // sema assumes that "clangd::" is a typo of "clang::" and uses - // "clang::" as the specified scope in: - // namespace clang { clangd::X; } - // In this case, we use the "typo" specifier as extra scope instead - // of using the scope assumed by sema. - if (!Spelling || llvm::StringRef(SpecifiedNS).ends_with(*Spelling)) { - Result.ResolvedScope = std::move(SpecifiedNS); + } else if (const NamespaceBaseDecl *NSB = Nested->getAsNamespace()) { + if (const auto *NS = dyn_cast(NSB)) { + std::string SpecifiedNS = printNamespaceScope(*NS); + std::optional Spelling = getSpelledSpecifier(*SS, SM); + + // Check the specifier spelled in the source. + // If the resolved scope doesn't end with the spelled scope, the + // resolved scope may come from a sema typo correction. For example, + // sema assumes that "clangd::" is a typo of "clang::" and uses + // "clang::" as the specified scope in: + // namespace clang { clangd::X; } + // In this case, we use the "typo" specifier as extra scope instead + // of using the scope assumed by sema. + if (!Spelling || llvm::StringRef(SpecifiedNS).ends_with(*Spelling)) { + Result.ResolvedScope = std::move(SpecifiedNS); + } else { + Result.UnresolvedScope = std::move(*Spelling); + } } else { - Result.UnresolvedScope = std::move(*Spelling); + Result.ResolvedScope = printNamespaceScope(*cast(NSB)->getNamespace()); } - } else if (const auto *ANS = Nested->getAsNamespaceAlias()) { - Result.ResolvedScope = printNamespaceScope(*ANS->getNamespace()); } else { // We don't fix symbols in scopes that are not top-level e.g. class // members, as we don't collect includes for them. diff --git a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp index 00c05ebdb5216..67fc451a6a1a1 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp @@ -173,7 +173,8 @@ findInsertionPoint(const Tweak::Selection &Inputs, if (SM.isBeforeInTranslationUnit(Inputs.Cursor, U->getUsingLoc())) // "Usings" is sorted, so we're done. break; - if (const auto *Namespace = U->getQualifier()->getAsNamespace()) { + if (const auto *Namespace = dyn_cast_if_present( + U->getQualifier()->getAsNamespace())) { if (Namespace->getCanonicalDecl() == QualifierToRemove.getNestedNameSpecifier() ->getAsNamespace() @@ -232,7 +233,10 @@ findInsertionPoint(const Tweak::Selection &Inputs, bool isNamespaceForbidden(const Tweak::Selection &Inputs, const NestedNameSpecifier &Namespace) { - std::string NamespaceStr = printNamespaceScope(*Namespace.getAsNamespace()); + const auto *NS = dyn_cast(Namespace.getAsNamespace()); + if (!NS) + return true; + std::string NamespaceStr = printNamespaceScope(*NS); for (StringRef Banned : Config::current().Style.FullyQualifiedNamespaces) { StringRef PrefixMatch = NamespaceStr; diff --git a/clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt b/clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt index 59475b0dfd3d2..1d6e38088ad67 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt +++ b/clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt @@ -14,9 +14,9 @@ set(LLVM_LINK_COMPONENTS add_clang_library(clangDaemonTweaks OBJECT AddUsing.cpp AnnotateHighlightings.cpp - DumpAST.cpp DefineInline.cpp DefineOutline.cpp + DumpAST.cpp ExpandDeducedType.cpp ExpandMacro.cpp ExtractFunction.cpp @@ -24,6 +24,7 @@ add_clang_library(clangDaemonTweaks OBJECT MemberwiseConstructor.cpp ObjCLocalizeStringLiteral.cpp ObjCMemberwiseInitializer.cpp + OverridePureVirtuals.cpp PopulateSwitch.cpp RawStringLiteral.cpp RemoveUsingNamespace.cpp diff --git a/clang-tools-extra/clangd/refactor/tweaks/OverridePureVirtuals.cpp b/clang-tools-extra/clangd/refactor/tweaks/OverridePureVirtuals.cpp new file mode 100644 index 0000000000000..16febeca70809 --- /dev/null +++ b/clang-tools-extra/clangd/refactor/tweaks/OverridePureVirtuals.cpp @@ -0,0 +1,374 @@ +//===--- OverridePureVirtuals.cpp --------------------------------*- 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 +// +//===----------------------------------------------------------------------===// +// +// Tweak to automatically generate stubs for pure virtual methods inherited from +// base classes. +// +// Purpose: +// - Simplifies making a derived class concrete by automating the creation of +// required method overrides from abstract bases. +// +// Tweak Summary: +// +// 1. Activation Conditions (prepare): +// - The tweak activates when the cursor is over a C++ class definition. +// - The class must be abstract (it, or its base classes, have unimplemented +// pure virtual functions). +// - It must also inherit from at least one other abstract class. +// +// 2. Identifying Missing Methods: +// - The tweak scans the inheritance hierarchy of the current class. +// - It identifies all unique pure virtual methods from base classes +// that are not yet implemented or overridden. +// - These missing methods are then grouped by their original access +// specifier (e.g., public, protected). +// +// 3. Code Generation and Insertion: +// - For each group of missing methods, stubs are inserted. +// - If an access specifier section (like `public:`) exists, stubs are +// inserted there; otherwise, a new section is created and appended. +// - Each generated stub includes the `override` keyword, a `// TODO:` +// comment, and a `static_assert(false, ...)` to force a compile-time +// error if the method remains unimplemented. +// - The base method's signature is adjusted (e.g., `virtual` and `= 0` +// are removed for the override). +// +// 4. Code Action Provided: +// - A single code action titled "Override pure virtual methods" is offered. +// - Applying this action results in a single source file modification +// containing all the generated method stubs. +// +// Example: +// +// class Base { +// public: +// virtual void publicMethod() = 0; +// protected: +// virtual auto privateMethod() const -> int = 0; +// }; +// +// Before: +// // cursor here +// class Derived : public Base {}^; +// +// After: +// +// class Derived : public Base { +// public: +// void publicMethod() override { +// // TODO: Implement this pure virtual method. +// static_assert(false, "Method `publicMethod` is not implemented."); +// } +// +// protected: +// auto privateMethod() const -> int override { +// // TODO: Implement this pure virtual method. +// static_assert(false, "Method `privateMethod` is not implemented."); +// } +// }; +// +//===----------------------------------------------------------------------===// + +#include "refactor/Tweak.h" +#include "support/Token.h" + +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Tooling/Core/Replacement.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/Support/FormatVariadic.h" +#include + +namespace clang { +namespace clangd { +namespace { + +// This function removes the "virtual" and the "= 0" at the end; +// e.g.: +// "virtual void foo(int var = 0) = 0" // input. +// "void foo(int var = 0)" // output. +std::string removePureVirtualSyntax(const std::string &MethodDecl, + const LangOptions &LangOpts) { + assert(!MethodDecl.empty()); + + TokenStream TS = lex(MethodDecl, LangOpts); + + std::string DeclString; + for (const clangd::Token &Tk : TS.tokens()) { + if (Tk.Kind == clang::tok::raw_identifier && Tk.text() == "virtual") + continue; + + // If the ending two tokens are "= 0", we break here and we already have the + // method's string without the pure virtual syntax. + const auto &Next = Tk.next(); + if (Next.next().Kind == tok::eof && Tk.Kind == clang::tok::equal && + Next.text() == "0") + break; + + DeclString += Tk.text(); + if (Tk.Kind != tok::l_paren && Next.Kind != tok::comma && + Next.Kind != tok::r_paren && Next.Kind != tok::l_paren) + DeclString += ' '; + } + // Trim the last whitespace. + if (DeclString.back() == ' ') + DeclString.pop_back(); + + return DeclString; +} + +class OverridePureVirtuals final : public Tweak { +public: + const char *id() const final; // defined by REGISTER_TWEAK. + bool prepare(const Selection &Sel) override; + Expected apply(const Selection &Sel) override; + std::string title() const override { return "Override pure virtual methods"; } + llvm::StringLiteral kind() const override { + return CodeAction::QUICKFIX_KIND; + } + +private: + // Stores the CXXRecordDecl of the class being modified. + const CXXRecordDecl *CurrentDeclDef = nullptr; + // Stores pure virtual methods that need overriding, grouped by their original + // access specifier. + llvm::MapVector> + MissingMethodsByAccess; + // Stores the source locations of existing access specifiers in CurrentDecl. + llvm::MapVector AccessSpecifierLocations; + // Helper function to gather information before applying the tweak. + void collectMissingPureVirtuals(); +}; + +REGISTER_TWEAK(OverridePureVirtuals) + +// Function to get all unique pure virtual methods from the entire +// base class hierarchy of CurrentDeclDef. +llvm::SmallVector +getAllUniquePureVirtualsFromBaseHierarchy( + const clang::CXXRecordDecl *CurrentDeclDef) { + llvm::SmallVector AllPureVirtualsInHierarchy; + llvm::DenseSet CanonicalPureVirtualsSeen; + + if (!CurrentDeclDef || !CurrentDeclDef->getDefinition()) + return AllPureVirtualsInHierarchy; + + const clang::CXXRecordDecl *Def = CurrentDeclDef->getDefinition(); + + Def->forallBases([&](const clang::CXXRecordDecl *BaseDefinition) { + for (const clang::CXXMethodDecl *Method : BaseDefinition->methods()) { + if (Method->isPureVirtual() && + CanonicalPureVirtualsSeen.insert(Method->getCanonicalDecl()).second) + AllPureVirtualsInHierarchy.emplace_back(Method); + } + // Continue iterating through all bases. + return true; + }); + + return AllPureVirtualsInHierarchy; +} + +// Gets canonical declarations of methods already overridden or implemented in +// class D. +llvm::SetVector +getImplementedOrOverriddenCanonicals(const CXXRecordDecl *D) { + llvm::SetVector ImplementedSet; + for (const CXXMethodDecl *M : D->methods()) { + // If M provides an implementation for any virtual method it overrides. + // A method is an "implementation" if it's virtual and not pure. + // Or if it directly overrides a base method. + for (const CXXMethodDecl *OverriddenM : M->overridden_methods()) + ImplementedSet.insert(OverriddenM->getCanonicalDecl()); + } + return ImplementedSet; +} + +// Get the location of every colon of the `AccessSpecifier`. +llvm::MapVector +getSpecifierLocations(const CXXRecordDecl *D) { + llvm::MapVector Locs; + for (auto *DeclNode : D->decls()) { + if (const auto *ASD = llvm::dyn_cast(DeclNode)) + Locs[ASD->getAccess()] = ASD->getColonLoc(); + } + return Locs; +} + +bool hasAbstractBaseAncestor(const clang::CXXRecordDecl *CurrentDecl) { + assert(CurrentDecl && CurrentDecl->getDefinition()); + + return llvm::any_of( + CurrentDecl->getDefinition()->bases(), [](CXXBaseSpecifier BaseSpec) { + const auto *D = BaseSpec.getType()->getAsCXXRecordDecl(); + const auto *Def = D ? D->getDefinition() : nullptr; + return Def && Def->isAbstract(); + }); +} + +// The tweak is available if the selection is over an abstract C++ class +// definition that also inherits from at least one other abstract class. +bool OverridePureVirtuals::prepare(const Selection &Sel) { + const SelectionTree::Node *Node = Sel.ASTSelection.commonAncestor(); + if (!Node) + return false; + + // Make sure we have a definition. + CurrentDeclDef = Node->ASTNode.get(); + if (!CurrentDeclDef || !CurrentDeclDef->getDefinition()) + return false; + + // From now on, we should work with the definition. + CurrentDeclDef = CurrentDeclDef->getDefinition(); + + // Only offer for abstract classes with abstract bases. + return CurrentDeclDef->isAbstract() && + hasAbstractBaseAncestor(CurrentDeclDef); +} + +// Collects all pure virtual methods from base classes that `CurrentDeclDef` has +// not yet overridden, grouped by their original access specifier. +// +// Results are stored in `MissingMethodsByAccess` and `AccessSpecifierLocations` +// is also populated. +void OverridePureVirtuals::collectMissingPureVirtuals() { + if (!CurrentDeclDef) + return; + + AccessSpecifierLocations = getSpecifierLocations(CurrentDeclDef); + MissingMethodsByAccess.clear(); + + // Get all unique pure virtual methods from the entire base class hierarchy. + llvm::SmallVector AllPureVirtualsInHierarchy = + getAllUniquePureVirtualsFromBaseHierarchy(CurrentDeclDef); + + // Get methods already implemented or overridden in CurrentDecl. + const auto ImplementedOrOverriddenSet = + getImplementedOrOverriddenCanonicals(CurrentDeclDef); + + // Filter AllPureVirtualsInHierarchy to find those not in + // ImplementedOrOverriddenSet, which needs to be overriden. + for (const CXXMethodDecl *BaseMethod : AllPureVirtualsInHierarchy) { + bool AlreadyHandled = ImplementedOrOverriddenSet.contains(BaseMethod); + if (!AlreadyHandled) + MissingMethodsByAccess[BaseMethod->getAccess()].emplace_back(BaseMethod); + } +} + +std::string generateOverrideString(const CXXMethodDecl *Method, + const LangOptions &LangOpts) { + std::string MethodDecl; + auto OS = llvm::raw_string_ostream(MethodDecl); + Method->print(OS); + + return llvm::formatv( + "\n {0} override {{\n" + " // TODO: Implement this pure virtual method.\n" + " static_assert(false, \"Method `{1}` is not implemented.\");\n" + " }", + removePureVirtualSyntax(MethodDecl, LangOpts), Method->getName()) + .str(); +} + +// Free function to generate the string for a group of method overrides. +std::string generateOverridesStringForGroup( + llvm::SmallVector Methods, + const LangOptions &LangOpts) { + llvm::SmallVector MethodsString; + MethodsString.reserve(Methods.size()); + + for (const CXXMethodDecl *Method : Methods) { + MethodsString.emplace_back(generateOverrideString(Method, LangOpts)); + } + + return llvm::join(MethodsString, "\n") + '\n'; +} + +Expected OverridePureVirtuals::apply(const Selection &Sel) { + // The correctness of this tweak heavily relies on the accurate population of + // these members. + collectMissingPureVirtuals(); + // The `prepare` should prevent this. If the prepare identifies an abstract + // method, then is must have missing methods. + assert(!MissingMethodsByAccess.empty()); + + const auto &SM = Sel.AST->getSourceManager(); + const auto &LangOpts = Sel.AST->getLangOpts(); + + tooling::Replacements EditReplacements; + // Stores text for new access specifier sections that are not already present + // in the class. + // Example: + // public: // ... + // protected: // ... + std::string NewSectionsToAppendText; + + for (const auto &[AS, Methods] : MissingMethodsByAccess) { + assert(!Methods.empty()); + + std::string MethodsGroupString = + generateOverridesStringForGroup(Methods, LangOpts); + + auto *ExistingSpecLocIter = AccessSpecifierLocations.find(AS); + bool ASExists = ExistingSpecLocIter != AccessSpecifierLocations.end(); + if (ASExists) { + // Access specifier section already exists in the class. + // Get location immediately *after* the colon. + SourceLocation InsertLoc = + ExistingSpecLocIter->second.getLocWithOffset(1); + + // Create a replacement to insert the method declarations. + // The replacement is at InsertLoc, has length 0 (insertion), and uses + // InsertionText. + std::string InsertionText = MethodsGroupString; + tooling::Replacement Rep(SM, InsertLoc, 0, InsertionText); + if (auto Err = EditReplacements.add(Rep)) + return llvm::Expected(std::move(Err)); + } else { + // Access specifier section does not exist in the class. + // These methods will be grouped into NewSectionsToAppendText and added + // towards the end of the class definition. + NewSectionsToAppendText += + getAccessSpelling(AS).str() + ':' + MethodsGroupString; + } + } + + // After processing all access specifiers, add any newly created sections + // (stored in NewSectionsToAppendText) to the end of the class. + if (!NewSectionsToAppendText.empty()) { + // AppendLoc is the SourceLocation of the closing brace '}' of the class. + // The replacement will insert text *before* this closing brace. + SourceLocation AppendLoc = CurrentDeclDef->getBraceRange().getEnd(); + std::string FinalAppendText = std::move(NewSectionsToAppendText); + + if (!CurrentDeclDef->decls_empty() || !EditReplacements.empty()) { + FinalAppendText = '\n' + FinalAppendText; + } + + // Create a replacement to append the new sections. + tooling::Replacement Rep(SM, AppendLoc, 0, FinalAppendText); + if (auto Err = EditReplacements.add(Rep)) + return llvm::Expected(std::move(Err)); + } + + if (EditReplacements.empty()) { + return llvm::make_error( + "No changes to apply (internal error or no methods generated).", + llvm::inconvertibleErrorCode()); + } + + // Return the collected replacements as the effect of this tweak. + return Effect::mainFileEdit(SM, EditReplacements); +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/CMakeLists.txt b/clang-tools-extra/clangd/unittests/CMakeLists.txt index dffdcd5d014ca..d425070c7f3b7 100644 --- a/clang-tools-extra/clangd/unittests/CMakeLists.txt +++ b/clang-tools-extra/clangd/unittests/CMakeLists.txt @@ -131,6 +131,7 @@ add_unittest(ClangdUnitTests ClangdTests tweaks/MemberwiseConstructorTests.cpp tweaks/ObjCLocalizeStringLiteralTests.cpp tweaks/ObjCMemberwiseInitializerTests.cpp + tweaks/OverridePureVirtualsTests.cpp tweaks/PopulateSwitchTests.cpp tweaks/RawStringLiteralTests.cpp tweaks/RemoveUsingNamespaceTests.cpp diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp index 602f61d9ecb41..4d77f9d690ca0 100644 --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -838,7 +838,7 @@ TEST_F(TargetDeclTest, OverloadExpr) { )cpp"; // Sized deallocation is enabled by default in C++14 onwards. EXPECT_DECLS("CXXDeleteExpr", - "void operator delete(void *, unsigned long) noexcept"); + "void operator delete(void *, __size_t) noexcept"); } TEST_F(TargetDeclTest, DependentExprs) { diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp index 775278ccf694b..4a21dafed5e95 100644 --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -2794,7 +2794,7 @@ TEST(Hover, All) { })cpp", [](HoverInfo &HI) { HI.Name = "expression"; - HI.Type = "unsigned long"; + HI.Type = {"__size_t", "unsigned long"}; HI.Value = "1"; }}, { @@ -2804,7 +2804,7 @@ TEST(Hover, All) { })cpp", [](HoverInfo &HI) { HI.Name = "expression"; - HI.Type = "unsigned long"; + HI.Type = {"__size_t", "unsigned long"}; HI.Value = "1"; }}, { diff --git a/clang-tools-extra/clangd/unittests/tweaks/OverridePureVirtualsTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/OverridePureVirtualsTests.cpp new file mode 100644 index 0000000000000..b7dcbee1650ec --- /dev/null +++ b/clang-tools-extra/clangd/unittests/tweaks/OverridePureVirtualsTests.cpp @@ -0,0 +1,720 @@ +//===-- OverridePureVirtualsTests.cpp ---------------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#include "TweakTesting.h" +#include "gtest/gtest.h" + +namespace clang { +namespace clangd { +namespace { + +class OverridePureVirtualsTests : public TweakTest { +protected: + OverridePureVirtualsTests() : TweakTest("OverridePureVirtuals") {} +}; + +TEST_F(OverridePureVirtualsTests, MinimalUnavailable) { + EXPECT_UNAVAILABLE("class ^C {};"); +} + +TEST_F(OverridePureVirtualsTests, MinimalAvailable) { + EXPECT_AVAILABLE(R"cpp( +class B { public: virtual void Foo() = 0; }; +class ^C : public B {}; +)cpp"); +} + +TEST_F(OverridePureVirtualsTests, UnavailableWhenOverriden) { + EXPECT_UNAVAILABLE( + R"cpp( +class B { +public: + virtual void foo() = 0; +}; + +class ^D : public B { +public: + void foo() override; +}; +)cpp"); +} + +TEST_F(OverridePureVirtualsTests, AvailabilityNoOverride) { + EXPECT_AVAILABLE(R"cpp( +class Base { +public: +virtual ~Base() = default; +virtual void F1() = 0; +virtual void F2() = 0; +}; + +class ^Derived : public Base { +public: +}; + +)cpp"); +} + +TEST_F(OverridePureVirtualsTests, AvailabilityPartiallyOverridden) { + EXPECT_AVAILABLE(R"cpp( +class Base { +public: +virtual ~Base() = default; +virtual void F1() = 0; +virtual void F2() = 0; +}; + +class ^Derived : public Base { +public: +void F1() override; +}; +)cpp"); +} + +TEST_F(OverridePureVirtualsTests, EmptyDerivedClass) { + const char *Before = R"cpp( +class Base { +public: +virtual ~Base() = default; +virtual void F1() = 0; +virtual void F2(int P1, const int &P2) = 0; +}; + +class ^Derived : public Base {}; +)cpp"; + const auto *Expected = R"cpp( +class Base { +public: +virtual ~Base() = default; +virtual void F1() = 0; +virtual void F2(int P1, const int &P2) = 0; +}; + +class Derived : public Base { +public: + void F1() override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `F1` is not implemented."); + } + + void F2(int P1, const int & P2) override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `F2` is not implemented."); + } +}; +)cpp"; + auto Applied = apply(Before); + EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; +} + +TEST_F(OverridePureVirtualsTests, SingleBaseClassPartiallyImplemented) { + auto Applied = apply( + R"cpp( +class Base { +public: +virtual ~Base() = default; +virtual void F1() = 0; +virtual void F2() = 0; +}; + +class ^Derived : public Base { +public: + void F1() override; +}; +)cpp"); + + const auto *Expected = R"cpp( +class Base { +public: +virtual ~Base() = default; +virtual void F1() = 0; +virtual void F2() = 0; +}; + +class Derived : public Base { +public: + void F2() override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `F2` is not implemented."); + } + + void F1() override; +}; +)cpp"; + EXPECT_EQ(Applied, Expected) << "Applied result:\n" << Applied; +} + +TEST_F(OverridePureVirtualsTests, MultipleDirectBaseClasses) { + const char *Before = R"cpp( +class Base1 { +public: + virtual void func1() = 0; +}; +class Base2 { +protected: + virtual bool func2(char c) const = 0; +}; + +class ^Derived : public Base1, public Base2 {}; +)cpp"; + const auto *Expected = R"cpp( +class Base1 { +public: + virtual void func1() = 0; +}; +class Base2 { +protected: + virtual bool func2(char c) const = 0; +}; + +class Derived : public Base1, public Base2 { +public: + void func1() override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `func1` is not implemented."); + } +protected: + bool func2(char c) const override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `func2` is not implemented."); + } +}; +)cpp"; + auto Applied = apply(Before); + EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; +} + +TEST_F(OverridePureVirtualsTests, UnnamedParametersInBase) { + const char *Before = R"cpp( +struct S {}; +class Base { +public: + virtual void func(int, const S&, char*) = 0; +}; + +class ^Derived : public Base {}; +)cpp"; + + const auto *Expected = R"cpp( +struct S {}; +class Base { +public: + virtual void func(int, const S&, char*) = 0; +}; + +class Derived : public Base { +public: + void func(int, const S &, char *) override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `func` is not implemented."); + } +}; +)cpp"; + auto Applied = apply(Before); + EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; +} + +TEST_F(OverridePureVirtualsTests, DiamondInheritance) { + const char *Before = R"cpp( +class Top { +public: + virtual ~Top() = default; + virtual void diamond_func() = 0; +}; +class Left : virtual public Top {}; +class Right : virtual public Top {}; +class ^Bottom : public Left, public Right {}; +)cpp"; + const auto *Expected = R"cpp( +class Top { +public: + virtual ~Top() = default; + virtual void diamond_func() = 0; +}; +class Left : virtual public Top {}; +class Right : virtual public Top {}; +class Bottom : public Left, public Right { +public: + void diamond_func() override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `diamond_func` is not implemented."); + } +}; +)cpp"; + auto Applied = apply(Before); + EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; +} + +TEST_F(OverridePureVirtualsTests, MixedAccessSpecifiers) { + const char *Before = R"cpp( +class Base { +public: + virtual void pub_func() = 0; + virtual void pub_func2(char) const = 0; +protected: + virtual int prot_func(int x) const = 0; +}; + +class ^Derived : public Base { + int member; // Existing member +public: + Derived(int m) : member(m) {} +}; +)cpp"; + const auto *Expected = R"cpp( +class Base { +public: + virtual void pub_func() = 0; + virtual void pub_func2(char) const = 0; +protected: + virtual int prot_func(int x) const = 0; +}; + +class Derived : public Base { + int member; // Existing member +public: + void pub_func() override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `pub_func` is not implemented."); + } + + void pub_func2(char) const override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `pub_func2` is not implemented."); + } + + Derived(int m) : member(m) {} + +protected: + int prot_func(int x) const override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `prot_func` is not implemented."); + } +}; +)cpp"; + auto Applied = apply(Before); + EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; +} + +TEST_F(OverridePureVirtualsTests, OutOfOrderMixedAccessSpecifiers) { + const char *Before = R"cpp( +class Base { +public: + virtual void pub_func() = 0; + virtual void pub_func2(char) const = 0; +protected: + virtual int prot_func(int x) const = 0; +}; + +class ^Derived : public Base { + int member; // Existing member +protected: + void foo(); +public: + Derived(int m) : member(m) {} +}; +)cpp"; + const auto *Expected = R"cpp( +class Base { +public: + virtual void pub_func() = 0; + virtual void pub_func2(char) const = 0; +protected: + virtual int prot_func(int x) const = 0; +}; + +class Derived : public Base { + int member; // Existing member +protected: + int prot_func(int x) const override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `prot_func` is not implemented."); + } + + void foo(); +public: + void pub_func() override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `pub_func` is not implemented."); + } + + void pub_func2(char) const override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `pub_func2` is not implemented."); + } + + Derived(int m) : member(m) {} +}; +)cpp"; + auto Applied = apply(Before); + EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; +} + +TEST_F(OverridePureVirtualsTests, MultiAccessSpecifiersOverride) { + constexpr auto Before = R"cpp( +class Base { +public: + virtual void foo() = 0; +protected: + virtual void bar() = 0; +}; + +class ^Derived : public Base {}; +)cpp"; + + constexpr auto Expected = R"cpp( +class Base { +public: + virtual void foo() = 0; +protected: + virtual void bar() = 0; +}; + +class Derived : public Base { +public: + void foo() override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `foo` is not implemented."); + } +protected: + void bar() override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `bar` is not implemented."); + } +}; +)cpp"; + auto Applied = apply(Before); + EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; +} + +TEST_F(OverridePureVirtualsTests, AccessSpecifierAlreadyExisting) { + const char *Before = R"cpp( +class Base { +public: + virtual void func1() = 0; +}; + +class ^Derived : public Base { +public: +}; +)cpp"; + + const auto *Expected = R"cpp( +class Base { +public: + virtual void func1() = 0; +}; + +class Derived : public Base { +public: + void func1() override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `func1` is not implemented."); + } + +}; +)cpp"; + auto Applied = apply(Before); + EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; +} + +TEST_F(OverridePureVirtualsTests, ConstexprSpecifier) { + ExtraArgs.push_back("-std=c++20"); + + constexpr auto Before = R"cpp( +class B { +public: + constexpr virtual int getValue() const = 0; +}; + +class ^D : public B {}; +)cpp"; + + constexpr auto Expected = R"cpp( +class B { +public: + constexpr virtual int getValue() const = 0; +}; + +class D : public B { +public: + constexpr int getValue() const override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `getValue` is not implemented."); + } +}; +)cpp"; + auto Applied = apply(Before); + EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; +} + +TEST_F(OverridePureVirtualsTests, ConstevalSpecifier) { + ExtraArgs.push_back("-std=c++20"); + + constexpr auto Before = R"cpp( +class B { +public: + virtual consteval float calculate() = 0; +}; + +class ^D : public B {}; +)cpp"; + + constexpr auto Expected = R"cpp( +class B { +public: + virtual consteval float calculate() = 0; +}; + +class D : public B { +public: + consteval float calculate() override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `calculate` is not implemented."); + } +}; +)cpp"; + auto Applied = apply(Before); + EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; +} + +TEST_F(OverridePureVirtualsTests, LValueRefQualifier) { + constexpr auto Before = R"cpp( +class B { +public: + virtual void process() & = 0; +}; + +class ^D : public B {}; +)cpp"; + + constexpr auto Expected = R"cpp( +class B { +public: + virtual void process() & = 0; +}; + +class D : public B { +public: + void process() & override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `process` is not implemented."); + } +}; +)cpp"; + auto Applied = apply(Before); + EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; +} + +TEST_F(OverridePureVirtualsTests, RValueRefQualifier) { + constexpr auto Before = R"cpp( +class B { +public: + virtual bool isValid() && = 0; +}; + +class ^D : public B {}; +)cpp"; + + constexpr auto Expected = R"cpp( +class B { +public: + virtual bool isValid() && = 0; +}; + +class D : public B { +public: + bool isValid() && override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `isValid` is not implemented."); + } +}; +)cpp"; + auto Applied = apply(Before); + EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; +} + +TEST_F(OverridePureVirtualsTests, SimpleTrailingReturnType) { + constexpr auto Before = R"cpp( +class B { +public: + virtual auto getStatus() -> bool = 0; +}; + +class ^D : public B {}; +)cpp"; + + constexpr auto Expected = R"cpp( +class B { +public: + virtual auto getStatus() -> bool = 0; +}; + +class D : public B { +public: + auto getStatus() -> bool override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `getStatus` is not implemented."); + } +}; +)cpp"; + auto Applied = apply(Before); + EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; +} + +TEST_F(OverridePureVirtualsTests, ConstexprLValueRefAndTrailingReturn) { + ExtraArgs.push_back("-std=c++20"); + + constexpr auto Before = R"cpp( +class B { +public: + constexpr virtual auto getData() & -> const char * = 0; +}; + +class ^D : public B {}; +)cpp"; + + constexpr auto Expected = R"cpp( +class B { +public: + constexpr virtual auto getData() & -> const char * = 0; +}; + +class D : public B { +public: + constexpr auto getData() & -> const char * override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `getData` is not implemented."); + } +}; +)cpp"; + auto Applied = apply(Before); + EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; +} + +TEST_F(OverridePureVirtualsTests, ConstevalRValueRefAndTrailingReturn) { + ExtraArgs.push_back("-std=c++20"); + + constexpr auto Before = R"cpp( +class B { +public: + virtual consteval auto foo() && -> double = 0; +}; + +class ^D : public B {}; +)cpp"; + + constexpr auto Expected = R"cpp( +class B { +public: + virtual consteval auto foo() && -> double = 0; +}; + +class D : public B { +public: + consteval auto foo() && -> double override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `foo` is not implemented."); + } +}; +)cpp"; + auto Applied = apply(Before); + EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; +} + +TEST_F(OverridePureVirtualsTests, CombinedFeaturesWithTrailingReturnTypes) { + ExtraArgs.push_back("-std=c++20"); + + constexpr auto Before = R"cpp( +class B { +public: + virtual auto f1() & -> int = 0; + constexpr virtual auto f2() && -> int = 0; + virtual consteval auto f3() -> int = 0; + virtual auto f4() const & -> char = 0; + constexpr virtual auto f5() const && -> bool = 0; +}; + +class ^D : public B {}; +)cpp"; + + constexpr auto Expected = R"cpp( +class B { +public: + virtual auto f1() & -> int = 0; + constexpr virtual auto f2() && -> int = 0; + virtual consteval auto f3() -> int = 0; + virtual auto f4() const & -> char = 0; + constexpr virtual auto f5() const && -> bool = 0; +}; + +class D : public B { +public: + auto f1() & -> int override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `f1` is not implemented."); + } + + constexpr auto f2() && -> int override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `f2` is not implemented."); + } + + consteval auto f3() -> int override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `f3` is not implemented."); + } + + auto f4() const & -> char override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `f4` is not implemented."); + } + + constexpr auto f5() const && -> bool override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `f5` is not implemented."); + } +}; +)cpp"; + auto Applied = apply(Before); + EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; +} + +TEST_F(OverridePureVirtualsTests, DefaultParameters) { + ExtraArgs.push_back("-std=c++20"); + + constexpr auto Before = R"cpp( +class B { +public: + virtual void foo(int var = 0) = 0; +}; + +class ^D : public B {}; +)cpp"; + + constexpr auto Expected = R"cpp( +class B { +public: + virtual void foo(int var = 0) = 0; +}; + +class D : public B { +public: + void foo(int var = 0) override { + // TODO: Implement this pure virtual method. + static_assert(false, "Method `foo` is not implemented."); + } +}; +)cpp"; + auto Applied = apply(Before); + EXPECT_EQ(Expected, Applied) << "Applied result:\n" << Applied; +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 9eb3835fe8340..bccb0ca83c79c 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -58,9 +58,6 @@ Semantic Highlighting Compile flags ^^^^^^^^^^^^^ -- Added `BuiltinHeaders` config key which controls whether clangd's built-in - headers are used or ones extracted from the driver. - Hover ^^^^^ @@ -70,6 +67,14 @@ Code completion Code actions ^^^^^^^^^^^^ +- New ``Override pure virtual methods`` code action. When invoked on a class + definition, this action automatically generates C++ ``override`` declarations + for all pure virtual methods inherited from its base classes that have not yet + been implemented. The generated method stubs prompts the user for the actual + implementation. The overrides are intelligently grouped under their original + access specifiers (e.g., ``public``, ``protected``), creating new access + specifier blocks if necessary. + Signature help ^^^^^^^^^^^^^^ @@ -93,300 +98,21 @@ Improvements to clang-query arguments. So when porting a query to C++, remove all instances of trailing comma (otherwise C++ compiler will just complain about "expected expression"). -Improvements to include-cleaner -------------------------------- -- Deprecated the ``-insert`` and ``-remove`` command line options, and added - the ``-disable-remove`` and ``-disable-insert`` command line options as - replacements. The previous command line options were confusing because they - did not imply the default state of the option (which is inserts and removes - being enabled). The new options are easier to understand the semantics of. - Improvements to clang-tidy -------------------------- -- Changed the :program:`check_clang_tidy.py` tool to use FileCheck's - ``--match-full-lines`` instead of ``strict-whitespace`` for ``CHECK-FIXES`` - clauses. Added a ``--match-partial-fixes`` option to keep previous behavior on - specific tests. This may break tests for users with custom out-of-tree checks - who use :program:`check_clang_tidy.py` as-is. - -- Improved :program:`clang-tidy-diff.py` script. Add the `-warnings-as-errors` - argument to treat warnings as errors. - -- Improved :program:`clang-tidy` to show `CheckOptions` only for checks enabled - in `Checks` when running ``--dump-config``. - -- Fixed bug in :program:`clang-tidy` by which `HeaderFilterRegex` did not take - effect when passed via the `.clang-tidy` file. - -- Fixed bug in :program:`run_clang_tidy.py` where the program would not - correctly display the checks enabled by the top-level `.clang-tidy` file. - New checks ^^^^^^^^^^ -- New :doc:`bugprone-capturing-this-in-member-variable - ` check. - - Finds lambda captures and ``bind`` function calls that capture the ``this`` - pointer and store it as class members without handle the copy and move - constructors and the assignments. - -- New :doc:`bugprone-misleading-setter-of-reference - ` check. - - Finds setter-like member functions that take a pointer parameter and set a - reference member of the same class with the pointed value. - -- New :doc:`bugprone-unintended-char-ostream-output - ` check. - - Finds unintended character output from ``unsigned char`` and ``signed char`` - to an ``ostream``. - -- New :doc:`cppcoreguidelines-use-enum-class - ` check. - - Finds unscoped (non-class) ``enum`` declarations and suggests using - ``enum class`` instead. - -- New :doc:`llvm-prefer-static-over-anonymous-namespace - ` check. - - Finds function and variable declarations inside anonymous namespace and - suggests replacing them with ``static`` declarations. - -- New :doc:`modernize-use-scoped-lock - ` check. - - Finds uses of ``std::lock_guard`` and suggests replacing them with C++17's - alternative ``std::scoped_lock``. - -- New :doc:`portability-avoid-pragma-once - ` check. - - Finds uses of ``#pragma once`` and suggests replacing them with standard - include guards (``#ifndef``/``#define``/``#endif``) for improved portability. - -- New :doc:`readability-ambiguous-smartptr-reset-call - ` check. - - Finds potentially erroneous calls to ``reset`` method on smart pointers when - the pointee type also has a ``reset`` method. - -- New :doc:`readability-use-concise-preprocessor-directives - ` check. - - Finds uses of ``#if`` that can be simplified to ``#ifdef`` or ``#ifndef`` and, - since C23 and C++23, uses of ``#elif`` that can be simplified to ``#elifdef`` - or ``#elifndef``. - New check aliases ^^^^^^^^^^^^^^^^^ Changes in existing checks ^^^^^^^^^^^^^^^^^^^^^^^^^^ -- Improved :doc:`bugprone-crtp-constructor-accessibility - ` check by fixing - false positives on deleted constructors that cannot be used to construct - objects, even if they have public or protected access. - -- Improved :doc:`bugprone-exception-escape - ` check to print stack trace - of a potentially escaped exception. - -- Added an option to :doc:`bugprone-multi-level-implicit-pointer-conversion - ` to - choose whether to enable the check in C code or not. - -- Improved :doc:`bugprone-optional-value-conversion - ` check to detect - conversion in argument of ``std::make_optional``. - -- Improved :doc:`bugprone-sizeof-expression - ` check by adding - `WarnOnSizeOfInLoopTermination` option to detect misuses of ``sizeof`` - expression in loop conditions. - -- Improved :doc:`bugprone-string-constructor - ` check to find suspicious - calls of ``std::string`` constructor with char pointer, start position and - length parameters. - -- Improved :doc:`bugprone-unchecked-optional-access - ` fixing false - positives from smart pointer accessors repeated in checking ``has_value`` - and accessing ``value``. The option `IgnoreSmartPointerDereference` should - no longer be needed and will be removed. Also fixing false positive from - const reference accessors to objects containing optional member. - -- Improved :doc:`bugprone-unsafe-functions - ` check to allow specifying - additional C++ member functions to match. - -- Improved :doc:`cert-err33-c - ` check by fixing false positives when - a function name is just prefixed with a targeted function name. - -- Improved :doc:`concurrency-mt-unsafe - ` check by fixing a false positive - where ``strerror`` was flagged as MT-unsafe. - -- Improved :doc:`cppcoreguidelines-avoid-goto - ` check by adding the option - `IgnoreMacros` to ignore ``goto`` labels defined in macros. - -- Improved :doc:`cppcoreguidelines-interfaces-global-init - ` check by - fixing false positives on uses of ``constinit`` variables. - -- Improved :doc:`cppcoreguidelines-missing-std-forward - ` check by adding a - flag to specify the function used for forwarding instead of ``std::forward``. - -- Improved :doc:`cppcoreguidelines-pro-bounds-pointer-arithmetic - ` check by - fixing false positives when calling indexing operators that do not perform - pointer arithmetic in template, for example ``std::map::operator[]`` and - when pointer arithmetic was used through type aliases. - -- Improved :doc:`cppcoreguidelines-rvalue-reference-param-not-moved - ` check - by adding a flag to specify the function used for moving instead of - ``std::move``. - -- Improved :doc:`cppcoreguidelines-special-member-functions - ` check by - adding the option `IgnoreMacros` to ignore classes defined in macros. - -- Improved :doc:`google-readability-namespace-comments - ` check by adding - the option `AllowOmittingNamespaceComments` to accept if a namespace comment - is omitted entirely. - -- Improved :doc:`hicpp-avoid-goto - ` check by adding the option - `IgnoreMacros` to ignore ``goto`` labels defined in macros. - -- Improved :doc:`hicpp-special-member-functions - ` check by adding the - option `IgnoreMacros` to ignore classes defined in macros. - -- Improved :doc:`llvm-namespace-comment - ` check by adding the option - `AllowOmittingNamespaceComments` to accept if a namespace comment is omitted - entirely. - -- Improved :doc:`misc-const-correctness - ` check by adding the option - `AllowedTypes`, that excludes specified types from const-correctness - checking and fixing false positives when modifying variant by ``operator[]`` - with template in parameters and supporting to check pointee mutation by - `AnalyzePointers` option and fixing false positives when using const array - type. - -- Improved :doc:`misc-include-cleaner - ` check by adding the options - `UnusedIncludes` and `MissingIncludes`, which specify whether the check should - report unused or missing includes respectively. - -- Improved :doc:`misc-redundant-expression - ` check by providing additional - examples and fixing some macro related false positives. - -- Improved :doc:`misc-unconventional-assign-operator - ` check by fixing - false positives when copy assignment operator function in a template class - returns the result of another assignment to ``*this`` (``return *this=...``). - -- Improved :doc:`misc-unused-using-decls - ` check by fixing false positives - on ``operator""`` with template parameters. - -- Improved :doc:`misc-use-internal-linkage - ` check by fix false positives - for function or variable in header file which contains macro expansion and - excluding variables with ``thread_local`` storage class specifier from being - matched. - -- Improved :doc:`modernize-pass-by-value - ` check by fixing false positives - when class passed by const-reference had a private move constructor. - -- Improved :doc:`modernize-type-traits - ` check by detecting more type traits. - -- Improved :doc:`modernize-use-default-member-init - ` check by matching - arithmetic operations, ``constexpr`` and ``static`` values, and detecting - explicit casting of built-in types within member list initialization. - -- Improved :doc:`modernize-use-designated-initializers - ` check by avoiding - diagnosing designated initializers for ``std::array`` initializations. - -- Improved :doc:`modernize-use-ranges - ` check by updating suppress - warnings logic for ``nullptr`` in ``std::find``. - -- Improved :doc:`modernize-use-starts-ends-with - ` check by adding more - matched scenarios of ``find`` and ``rfind`` methods and fixing false - positives when those methods were called with 3 arguments. - -- Improved :doc:`modernize-use-std-numbers - ` check to support math - functions of different precisions. - -- Improved :doc:`modernize-use-trailing-return-type - ` check by adding - support to modernize lambda signatures to use trailing return type and adding - two new options: `TransformFunctions` and `TransformLambdas` to control - whether function declarations and lambdas should be transformed by the check. - Fixed false positives when lambda was matched as a function in C++11 mode. - -- Improved :doc:`performance-move-const-arg - ` check by fixing false - negatives on ternary operators calling ``std::move``. - -- Improved :doc:`performance-unnecessary-value-param - ` check performance by - tolerating fix-it breaking compilation when functions is used as pointers - to avoid matching usage of functions within the current compilation unit. - Added an option `IgnoreCoroutines` with the default value `true` to - suppress this check for coroutines where passing by reference may be unsafe. - -- Improved :doc:`readability-convert-member-functions-to-static - ` check by - fixing false positives on member functions with an explicit object parameter. - -- Improved :doc:`readability-function-size - ` check by adding new option - `CountMemberInitAsStmt` that allows counting class member initializers in - constructors as statements. - -- Improved :doc:`readability-math-missing-parentheses - ` check by fixing - false negatives where math expressions are the operand of assignment operators - or comparison operators. - -- Improved :doc:`readability-named-parameter - ` check by adding the option - `InsertPlainNamesInForwardDecls` to insert parameter names without comments - for forward declarations only. - -- Improved :doc:`readability-qualified-auto - ` check by adding the option - `AllowedTypes`, that excludes specified types from adding qualifiers. - -- Improved :doc:`readability-redundant-inline-specifier - ` check by fixing - false positives on out-of-line explicitly defaulted functions. - -- Improved :doc:`readability-redundant-smartptr-get - ` check by fixing - some false positives involving smart pointers to arrays. +- Improved :doc:`bugprone-infinite-loop + ` check by adding detection for + variables introduced by structured bindings. Removed checks ^^^^^^^^^^^^^^ @@ -414,3 +140,4 @@ Improvements to pp-trace Clang-tidy Visual Studio plugin ------------------------------- + diff --git a/clang-tools-extra/docs/clang-tidy/Contributing.rst b/clang-tools-extra/docs/clang-tidy/Contributing.rst index 9611c655886f2..ad12b2343d1e9 100644 --- a/clang-tools-extra/docs/clang-tidy/Contributing.rst +++ b/clang-tools-extra/docs/clang-tidy/Contributing.rst @@ -19,11 +19,11 @@ check, the rest of this document explains how to do this. There are a few tools particularly useful when developing clang-tidy checks: * ``add_new_check.py`` is a script to automate the process of adding a new - check, it will create the check, update the CMake file and create a test; + check; it will create the check, update the CMake file and create a test. * ``rename_check.py`` does what the script name suggests, renames an existing - check; + check. * :program:`pp-trace` logs method calls on `PPCallbacks` for a source file - and is invaluable in understanding the preprocessor mechanism; + and is invaluable in understanding the preprocessor mechanism. * :program:`clang-query` is invaluable for interactive prototyping of AST matchers and exploration of the Clang AST; * `clang-check`_ with the ``-ast-dump`` (and optionally ``-ast-dump-filter``) @@ -47,7 +47,7 @@ implemented as a: + *Clang diagnostic*: if the check is generic enough, targets code patterns that most probably are bugs (rather than style or readability issues), can be - implemented effectively and with extremely low false positive rate, it may + implemented effectively and with extremely low false-positive rate, it may make a good Clang diagnostic. + *Clang static analyzer check*: if the check requires some sort of control flow @@ -77,7 +77,7 @@ make sure that you enable the ``clang`` and ``clang-tools-extra`` projects to build :program:`clang-tidy`. Because your new check will have associated documentation, you will also want to install `Sphinx `_ and enable it in the CMake configuration. -To save build time of the core Clang libraries you may want to only enable the ``X86`` +To save build time of the core Clang libraries, you may want to only enable the ``X86`` target in the CMake configuration. @@ -130,7 +130,7 @@ So you have an idea of a useful check for :program:`clang-tidy`. First, if you're not familiar with LLVM development, read through the `Getting Started with the LLVM System`_ document for instructions on setting up your workflow and the `LLVM Coding Standards`_ document to familiarize yourself with the coding -style used in the project. For code reviews we currently use `LLVM Github`_, +style used in the project. For code reviews, we currently use `LLVM Github`_, though historically we used Phabricator. .. _Getting Started with the LLVM System: https://llvm.org/docs/GettingStarted.html @@ -141,7 +141,7 @@ Next, you need to decide which module the check belongs to. Modules are located in subdirectories of `clang-tidy/ `_ and contain checks targeting a certain aspect of code quality (performance, -readability, etc.), certain coding style or standard (Google, LLVM, CERT, etc.) +readability, etc.), a certain coding style or standard (Google, LLVM, CERT, etc.) or a widely used API (e.g. MPI). Their names are the same as the user-facing check group names described :ref:`above `. @@ -166,7 +166,7 @@ The ``add_new_check.py`` script will: * create a documentation file and include it into the ``docs/clang-tidy/checks/list.rst``. -Let's see in more detail at the check class definition: +Let's look at the check class definition in more detail: .. code-block:: c++ @@ -200,7 +200,7 @@ In our case the check needs to operate on the AST level and it overrides the preprocessor level, we'd need instead to override the ``registerPPCallbacks`` method. -In the ``registerMatchers`` method we create an AST Matcher (see `AST Matchers`_ +In the ``registerMatchers`` method, we create an AST Matcher (see `AST Matchers`_ for more information) that will find the pattern in the AST that we want to inspect. The results of the matching are passed to the ``check`` method, which can further inspect them and report diagnostics. @@ -320,7 +320,7 @@ the ``add_new_check.py`` script: Developing your check incrementally ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The best way to develop your check is to start with the simple test cases and increase +The best way to develop your check is to start with simple test cases and increase complexity incrementally. The test file created by the ``add_new_check.py`` script is a starting point for your test cases. A rough outline of the process looks like this: @@ -393,7 +393,7 @@ good way to catch things you forgot to account for in your matchers. However, t LLVM code base may be insufficient for testing purposes as it was developed against a particular set of coding styles and quality measures. The larger the corpus of code the check is tested against, the higher confidence the community will have in the -check's efficacy and false positive rate. +check's efficacy and false-positive rate. Some suggestions to ensure your check is robust: @@ -406,10 +406,10 @@ Some suggestions to ensure your check is robust: - Define template classes that contain code matched by your check. - Define template specializations that contain code matched by your check. - Test your check under both Windows and Linux environments. -- Watch out for high false positive rates. Ideally, a check would have no false +- Watch out for high false-positive rates. Ideally, a check would have no false positives, but given that matching against an AST is not control- or data flow- - sensitive, a number of false positives are expected. The higher the false - positive rate, the less likely the check will be adopted in practice. + sensitive, a number of false positives are expected. The higher the + false-positive rate, the less likely the check will be adopted in practice. Mechanisms should be put in place to help the user manage false positives. - There are two primary mechanisms for managing false positives: supporting a code pattern which allows the programmer to silence the diagnostic in an ad @@ -428,10 +428,10 @@ Documenting your check The ``add_new_check.py`` script creates entries in the `release notes `_, the list of checks and a new file for the check documentation itself. It is recommended that you -have a concise summation of what your check does in a single sentence that is repeated +have a concise summary of what your check does in a single sentence that is repeated in the release notes, as the first sentence in the doxygen comments in the header file for your check class and as the first sentence of the check documentation. Avoid the -phrase "this check" in your check summation and check documentation. +phrase "this check" in your check summary and check documentation. If your check relates to a published coding guideline (C++ Core Guidelines, MISRA, etc.) or style guide, provide links to the relevant guideline or style guide sections in your @@ -443,10 +443,10 @@ If there are exceptions or limitations to your check, document them thoroughly. will help users understand the scope of the diagnostics and fix-its provided by the check. Building the target ``docs-clang-tools-html`` will run the Sphinx documentation generator -and create documentation HTML files in the tools/clang/tools/extra/docs/html directory in +and create HTML documentation files in the tools/clang/tools/extra/docs/html directory in your build tree. Make sure that your check is correctly shown in the release notes and the list of checks. Make sure that the formatting and structure of your check's documentation -looks correct. +look correct. Registering your Check @@ -503,11 +503,11 @@ Configuring Checks If a check needs configuration options, it can access check-specific options using the ``Options.get("SomeOption", DefaultValue)`` call in the check -constructor. In this case the check should also override the +constructor. In this case, the check should also override the ``ClangTidyCheck::storeOptions`` method to make the options provided by the check discoverable. This method lets :program:`clang-tidy` know which options the check implements and what the current values are (e.g. for the -``-dump-config`` command line option). +``-dump-config`` command-line option). .. code-block:: c++ @@ -576,7 +576,7 @@ typically the basic ``CHECK`` forms (``CHECK-MESSAGES`` and ``CHECK-FIXES``) are sufficient for clang-tidy tests. Note that the `FileCheck`_ documentation mostly assumes the default prefix (``CHECK``), and hence describes the directive as ``CHECK:``, ``CHECK-SAME:``, ``CHECK-NOT:``, etc. -Replace ``CHECK`` by either ``CHECK-FIXES`` or ``CHECK-MESSAGES`` for +Replace ``CHECK`` with either ``CHECK-FIXES`` or ``CHECK-MESSAGES`` for clang-tidy tests. An additional check enabled by ``check_clang_tidy.py`` ensures that @@ -590,7 +590,7 @@ appropriate ``RUN`` line in the ``test/clang-tidy`` directory. Use diagnostic messages and fixed code. It's advised to make the checks as specific as possible to avoid checks matching -to incorrect parts of the input. Use ``[[@LINE+X]]``/``[[@LINE-X]]`` +incorrect parts of the input. Use ``[[@LINE+X]]``/``[[@LINE-X]]`` substitutions and distinct function and variable names in the test code. Here's an example of a test using the ``check_clang_tidy.py`` script (the full @@ -606,7 +606,7 @@ source code is at `test/clang-tidy/checkers/google/readability-casting.cpp`_): // CHECK-FIXES: int b = a; } -To check more than one scenario in the same test file use +To check more than one scenario in the same test file, use ``-check-suffix=SUFFIX-NAME`` on ``check_clang_tidy.py`` command line or ``-check-suffixes=SUFFIX-NAME-1,SUFFIX-NAME-2,...``. With ``-check-suffix[es]=SUFFIX-NAME`` you need to replace your ``CHECK-*`` @@ -631,15 +631,15 @@ There are many dark corners in the C++ language, and it may be difficult to make your check work perfectly in all cases, especially if it issues fix-it hints. The most frequent pitfalls are macros and templates: -1. code written in a macro body/template definition may have a different meaning - depending on the macro expansion/template instantiation; -2. multiple macro expansions/template instantiations may result in the same code +1. Code written in a macro body/template definition may have a different meaning + depending on the macro expansion/template instantiation. +2. Multiple macro expansions/template instantiations may result in the same code being inspected by the check multiple times (possibly, with different meanings, see 1), and the same warning (or a slightly different one) may be issued by the check multiple times; :program:`clang-tidy` will deduplicate _identical_ warnings, but if the warnings are slightly different, all of them - will be shown to the user (and used for applying fixes, if any); -3. making replacements to a macro body/template definition may be fine for some + will be shown to the user (and used for applying fixes, if any). +3. Making replacements to a macro body/template definition may be fine for some macro expansions/template instantiations, but easily break some other expansions/instantiations. @@ -657,6 +657,29 @@ directory. The path to this directory is available in a lit test with the varia .. _FileCheck: https://llvm.org/docs/CommandGuide/FileCheck.html .. _test/clang-tidy/checkers/google/readability-casting.cpp: https://github.com/llvm/llvm-project/blob/main/clang-tools-extra/test/clang-tidy/checkers/google/readability-casting.cpp + +Submitting a Pull Request +------------------------- + +Before submitting a pull request, contributors are encouraged to run +:program:`clang-tidy` and :program:`clang-format` on their changes to ensure +code quality and catch potential issues. While :program:`clang-tidy` is not +currently enforced in CI, following this practice helps maintain code +consistency and prevent common errors. + +Here's a useful command to check your staged changes: + +.. code-block:: console + + $ git diff --staged -U0 | ./clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py \ + -j $(nproc) -path build/ -p1 -only-check-in-db + $ git clang-format + +Note that some warnings may be false positives or require careful consideration +before fixing. Use your judgment and feel free to discuss in the pull request +if you're unsure about a particular warning. + + Out-of-tree check plugins ------------------------- @@ -675,7 +698,7 @@ names of the checks to enable. $ clang-tidy --checks=-*,my-explicit-constructor -list-checks -load myplugin.so -There is no expectations regarding ABI and API stability, so the plugin must be +There are no expectations regarding ABI and API stability, so the plugin must be compiled against the version of clang-tidy that will be loading the plugin. The plugins can use threads, TLS, or any other facilities available to in-tree @@ -697,10 +720,10 @@ and write a version of `check_clang_tidy.py`_ to suit your needs. Running clang-tidy on LLVM -------------------------- -To test a check it's best to try it out on a larger code base. LLVM and Clang +To test a check, it's best to try it out on a larger code base. LLVM and Clang are the natural targets as you already have the source code around. The most convenient way to run :program:`clang-tidy` is with a compile command database; -CMake can automatically generate one, for a description of how to enable it see +CMake can automatically generate one; for a description of how to enable it, see `How To Setup Clang Tooling For LLVM`_. Once ``compile_commands.json`` is in place and a working version of :program:`clang-tidy` is in ``PATH`` the entire code base can be analyzed with ``clang-tidy/tool/run-clang-tidy.py``. The script @@ -712,18 +735,18 @@ warnings and errors. The script provides multiple configuration flags. * The default set of checks can be overridden using the ``-checks`` argument, - taking the identical format as :program:`clang-tidy` does. For example + taking the identical format as :program:`clang-tidy` does. For example, ``-checks=-*,modernize-use-override`` will run the ``modernize-use-override`` check only. -* To restrict the files examined you can provide one or more regex arguments +* To restrict the files examined, you can provide one or more regex arguments that the file names are matched against. ``run-clang-tidy.py clang-tidy/.*Check\.cpp`` will only analyze `clang-tidy` checks. It may also be necessary to restrict the header files that warnings are displayed from by using the ``-header-filter`` and ``-exclude-header-filter`` flags. They have the same behavior as the corresponding :program:`clang-tidy` flags. -* To apply suggested fixes ``-fix`` can be passed as an argument. This gathers +* To apply suggested fixes, ``-fix`` can be passed as an argument. This gathers all changes in a temporary directory and applies them. Passing ``-format`` will run clang-format over changed lines. @@ -772,7 +795,7 @@ There is only one argument that controls profile storage: * ``-store-check-profile=`` - By default reports are printed in tabulated format to stderr. When this option + By default, reports are printed in tabulated format to stderr. When this option is passed, these per-TU profiles are instead stored as JSON. If the prefix is not an absolute path, it is considered to be relative to the directory from where you have run :program:`clang-tidy`. All ``.`` and ``..`` diff --git a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp index baff90faa6eae..49cc13606f4c2 100644 --- a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp +++ b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp @@ -140,7 +140,6 @@ class ASTWalker : public RecursiveASTVisitor { return true; switch (Qual->getKind()) { case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: return true; case NestedNameSpecifier::TypeSpec: diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/infinite-loop.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/infinite-loop.cpp index bc14ece3f332c..9a58a7ae2f2ab 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/infinite-loop.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/infinite-loop.cpp @@ -711,3 +711,205 @@ void test_local_static_recursion() { while (i >= 0) p(0); // we don't know what p points to so no warning } + +struct PairVal { + int a; + int b; + PairVal(int a, int b) : a(a), b(b) {} +}; + +void structured_binding_infinite_loop1() { + auto [x, y] = PairVal(0, 0); + while (x < 10) { + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (x) are updated in the loop body [bugprone-infinite-loop] + y++; + } + while (y < 10) { + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (y) are updated in the loop body [bugprone-infinite-loop] + x++; + } +} + +void structured_binding_infinite_loop2() { + auto [x, y] = PairVal(0, 0); + while (x < 10) { + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (x) are updated in the loop body [bugprone-infinite-loop] + // No update to x or y + } + while (y < 10) { + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (y) are updated in the loop body [bugprone-infinite-loop] + // No update to x or y + } +} + +void structured_binding_not_infinite1() { + auto [x, y] = PairVal(0, 0); + while (x < 10) { + x++; + } + while (y < 10) { + y++; + } +} + +void volatile_structured_binding_in_condition() { + volatile auto [x, y] = PairVal(0, 0); + while (!x) {} +} + +void test_local_static_structured_binding_recursion() { + static auto [i, _] = PairVal(0, 0); + int j = 0; + + i--; + while (i >= 0) + test_local_static_structured_binding_recursion(); // no warning, recursively decrement i + for (; i >= 0;) + test_local_static_structured_binding_recursion(); // no warning, recursively decrement i + for (; i + j >= 0;) + test_local_static_structured_binding_recursion(); // no warning, recursively decrement i + for (; i >= 0; i--) + ; // no warning, i decrements + while (j >= 0) + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (j) are updated in the loop body [bugprone-infinite-loop] + test_local_static_structured_binding_recursion(); + + int (*p)(int) = 0; + + while (i >= 0) + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (i) are updated in the loop body [bugprone-infinite-loop] + p = 0; + while (i >= 0) + p(0); // we don't know what p points to so no warning +} + +struct S { int a; }; +void issue_138842_reduced() { + int x = 10; + auto [y] = S{1}; + + while (y < x) { + y++; + } +} + +namespace std { +template +struct pair { + T first; + U second; + + pair(T a, U b) : first(a), second(b) {} +}; +} + +template +void structured_binding_in_template_byval(T a, U b) { + auto [c, d] = std::pair(a,b); + + while (c < 10) { + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (c) are updated in the loop body [bugprone-infinite-loop] + d++; + } + + while (c < 10) { + c++; // no warning + } +} + +template +void structured_binding_in_template_bylref(T a, U b) { + auto p = std::pair(a,b); + auto& [c, d] = p; + + while (c < 10) { + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (c) are updated in the loop body [bugprone-infinite-loop] + d++; + } + + while (c < 10) { + c++; // no warning + } +} + +template +void structured_binding_in_template_byrref(T a, U b) { + auto p = std::pair(a,b); + auto&& [c, d] = p; + + while (c < 10) { + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (c) are updated in the loop body [bugprone-infinite-loop] + d++; + } + + while (c < 10) { + c++; // no warning + } +} + +void structured_binding_in_template_instantiation(int b) { + structured_binding_in_template_byval(b, 0); + structured_binding_in_template_bylref(b, 0); + structured_binding_in_template_byrref(b, 0); +} + +void array_structured_binding() { + int arr[2] = {0, 0}; + auto [x, y] = arr; + + while (x < 10) { + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (x) are updated in the loop body [bugprone-infinite-loop] + y++; + } + + while (y < 10) { + y++; // no warning + } +} + +namespace std { + using size_t = int; + template struct tuple_size; + template struct tuple_element; + template class tuple; + +namespace { + template + struct size_helper { static const T value = v; }; +} // namespace + +template +struct tuple_size> : size_helper {}; + +template +struct tuple_element> { + using type = __type_pack_element; +}; + +template class tuple {}; + +template +typename tuple_element>::type get(tuple); +} // namespace std + +std::tuple &get_chunk(); + +void test_structured_bindings_tuple() { + auto [buffer, size ] = get_chunk(); + int maxLen = 8; + + while (size < maxLen) { + // No warning. The loop is finite because 'size' is being incremented in each iteration and compared against 'maxLen' for termination + buffer[size++] = 2; + } +} + +void test_structured_bindings_tuple_ref() { + auto& [buffer, size ] = get_chunk(); + int maxLen = 8; + + while (size < maxLen) { + // No warning. The loop is finite because 'size' is being incremented in each iteration and compared against 'maxLen' for termination + buffer[size++] = 2; + } +} diff --git a/clang/cmake/caches/Fuchsia-stage2-instrumented.cmake b/clang/cmake/caches/Fuchsia-stage2-instrumented.cmake index ecd478aefdaee..b328f3d0ff9cf 100644 --- a/clang/cmake/caches/Fuchsia-stage2-instrumented.cmake +++ b/clang/cmake/caches/Fuchsia-stage2-instrumented.cmake @@ -43,3 +43,6 @@ set(CLANG_BOOTSTRAP_CMAKE_ARGS ${EXTRA_ARGS} -C ${CMAKE_CURRENT_LIST_DIR}/Fuchsia-stage2.cmake CACHE STRING "") + +# Do not use LLVM build for generating PGO data. +set(CLANG_PGO_TRAINING_USE_LLVM_BUILD OFF CACHE BOOL "") diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 0e21ef0244f78..d39ee49b432e5 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -4201,8 +4201,8 @@ the configuration (without a prefix: ``Auto``). * ``""`` means "arbitrary suffix" * ``"$"`` means "no suffix" - For example, if configured to ``"(_test)?$"``, then a header a.h would be seen - as the "main" include in both a.cc and a_test.cc. + For example, if configured to ``"(_test)?$"``, then a header a.h would be + seen as the "main" include in both a.cc and a_test.cc. .. _IncludeIsMainSourceRegex: @@ -6015,6 +6015,16 @@ the configuration (without a prefix: ``Auto``). #include "B/A.h" #include "B/a.h" #include "B/a.h" #include "a/b.h" + * ``bool IgnoreExtension`` When sorting includes in each block, only take file extensions into + account if two includes compare equal otherwise. + + .. code-block:: c++ + + true: false: + # include "A.h" vs. # include "A-util.h" + # include "A.inc" # include "A.h" + # include "A-util.h" # include "A.inc" + .. _SortJavaStaticImport: diff --git a/clang/docs/ClangTools.rst b/clang/docs/ClangTools.rst index 60e21590f9eb3..3216328bbb6a6 100644 --- a/clang/docs/ClangTools.rst +++ b/clang/docs/ClangTools.rst @@ -89,13 +89,50 @@ they'll be tracked here. The focus of this documentation is on the scope and features of the tools for other tool developers; each tool should provide its own user-focused documentation. -``clang-tidy`` +``Clang-Doc`` +------------- + +`Clang-Doc `_ is a tool for +generating C and C++ documentation from source code and comments. + +``Clang-Include-Fixer`` +----------------------- + +`Clang-Include-Fixer `_ +is a tool to automate the addition of missing ``#include`` directives in a C++ +file. It adds missing namespace qualifiers to unidentified symbols when +necessary and also removes unused headers. + +``Clang-Tidy`` -------------- -`clang-tidy `_ is a clang-based C++ +`Clang-Tidy `_ is a Clang-based C++ linter tool. It provides an extensible framework for building compiler-based static analyses detecting and fixing bug-prone patterns, performance, -portability and maintainability issues. +portability and maintainability issues. It also has checks for modernizing code +to newer language standards. + +``Clangd`` +---------- + +`Clangd `_ is a language server that can work with +many editors via a plugin. It understands your C++ code and adds smart +features to your editor: code completion, compile errors, go-to-definition and +more. + +``Modularize`` +-------------- + +`Modularize `_ is a standalone +tool that checks whether a set of headers provides the consistent definitions +required to use modules. + +``pp-trace`` +------------ + +`pp-trace `_ is a standalone tool +that traces preprocessor activity. It’s also used as a test of Clang’s +``PPCallbacks`` interface. Ideas for new Tools diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index f448a9a8db172..34e1bf150aef1 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -138,7 +138,7 @@ for support for non-standardized features, i.e. features not prefixed ``c_``, ``cxx_`` or ``objc_``. Another use of ``__has_feature`` is to check for compiler features not related -to the language standard, such as e.g. :doc:`AddressSanitizer +to the language standard, such as :doc:`AddressSanitizer `. If the ``-pedantic-errors`` option is given, ``__has_extension`` is equivalent @@ -377,8 +377,8 @@ Builtin Macros ``__FILE_NAME__`` Clang-specific extension that functions similar to ``__FILE__`` but only - renders the last path component (the filename) instead of an invocation - dependent full path to that file. + renders the last path component (the filename) instead of an + invocation-dependent full path to that file. ``__COUNTER__`` Defined to an integer value that starts at zero and is incremented each time @@ -716,7 +716,7 @@ See also :ref:`langext-__builtin_shufflevector`, :ref:`langext-__builtin_convert a NEON vector or an SVE vector, it's only available in C++ and uses normal bool conversions (that is, != 0). If it's an extension (OpenCL) vector, it's only available in C and OpenCL C. - And it selects base on signedness of the condition operands (OpenCL v1.1 s6.3.9). + And it selects based on signedness of the condition operands (OpenCL v1.1 s6.3.9). .. [#] sizeof can only be used on vector length specific SVE types. .. [#] Clang does not allow the address of an element to be taken while GCC allows this. This is intentional for vectors with a boolean element type and @@ -848,6 +848,14 @@ of different sizes and signs is forbidden in binary and ternary builtins. semantics, see `LangRef `_ for the comparison. + T __builtin_elementwise_maximumnum(T x, T y) return x or y, whichever is larger. Follows IEEE 754-2019 floating point types + semantics, see `LangRef + `_ + for the comparison. + T __builtin_elementwise_minimumnum(T x, T y) return x or y, whichever is smaller. Follows IEEE 754-2019 floating point types + semantics, see `LangRef + `_ + for the comparison. ============================================== ====================================================================== ========================================= @@ -857,7 +865,7 @@ Each builtin returns a scalar equivalent to applying the specified operation(x, y) as recursive even-odd pairwise reduction to all vector elements. ``operation(x, y)`` is repeatedly applied to each non-overlapping even-odd element pair with indices ``i * 2`` and ``i * 2 + 1`` with -``i in [0, Number of elements / 2)``. If the numbers of elements is not a +``i in [0, Number of elements / 2)``. If the number of elements is not a power of 2, the vector is widened with neutral elements for the reduction at the end to the next power of 2. @@ -1491,7 +1499,7 @@ C++14 digit separators Use ``__cpp_digit_separators`` to determine if support for digit separators using single quotes (for instance, ``10'000``) is enabled. At this time, there -is no corresponding ``__has_feature`` name +is no corresponding ``__has_feature`` name. C++14 generalized lambda capture ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1545,7 +1553,7 @@ C++ type aware allocators ^^^^^^^^^^^^^^^^^^^^^^^^^ Use ``__has_extension(cxx_type_aware_allocators)`` to determine the existence of -support for the future C++2d type aware allocator feature. For full details see +support for the future C++2d type aware allocator feature. For full details, see :doc:`C++ Type Aware Allocators ` for additional details. C11 @@ -1643,7 +1651,7 @@ Modules Use ``__has_feature(modules)`` to determine if Modules have been enabled. For example, compiling code with ``-fmodules`` enables the use of Modules. -More information could be found `here `_. +More information can be found `here `_. Language Extensions Back-ported to Previous Standards ===================================================== @@ -1878,7 +1886,7 @@ The following type trait primitives are supported by Clang. Those traits marked C++26 relocatable types, and types which were made trivially relocatable via the ``clang::trivial_abi`` attribute. This trait is deprecated and should be replaced by - ``__builtin_is_cpp_trivially_relocatable``. Note however that it is generally + ``__builtin_is_cpp_trivially_relocatable``. Note, however, that it is generally unsafe to relocate a C++-relocatable type with ``memcpy`` or ``memmove``; use ``__builtin_trivially_relocate``. * ``__builtin_is_cpp_trivially_relocatable`` (C++): Returns true if an object diff --git a/clang/docs/LibClang.rst b/clang/docs/LibClang.rst index 6c2b11ac7fc23..e747022b9c173 100644 --- a/clang/docs/LibClang.rst +++ b/clang/docs/LibClang.rst @@ -404,3 +404,9 @@ following situations are explicitly unsupported: compatible across library versions. * For the same reason as above, serializing objects from one version of the library and deserializing with a different version is also not supported. + +Note: because libclang is a wrapper around the compiler frontend, it is not a +`security-sensitive component`_ of the LLVM Project. Consider using a sandbox +or some other mitigation approach if processing untrusted input. + +.. _security-sensitive component: https://llvm.org/docs/Security.html#what-is-considered-a-security-issue diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 1eb3e369a302e..4f6e9a4b4bd1e 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -46,6 +46,7 @@ Potentially Breaking Changes ``endbr64`` instruction at the labels named as possible branch destinations, so it is not safe to use a register-controlled branch instruction to branch to one. (In line with gcc.) +- Added a sugar type `PredefinedSugarType` to improve diagnostic messages. (#GH143653) C/C++ Language Potentially Breaking Changes ------------------------------------------- @@ -76,6 +77,10 @@ C++ Specific Potentially Breaking Changes whose nested-name-specifier doesn't refer to a base class such as ``using CurrentClass::Foo;`` is now rejected in C++98 mode. +- For C++20 modules, the Reduced BMI mode will be the default option. This may introduce + regressions if your build system supports two-phase compilation model but haven't support + reduced BMI or it is a compiler bug or a bug in users code. + ABI Changes in This Version --------------------------- @@ -339,6 +344,7 @@ Non-comprehensive list of changes in this release - Added `__builtin_elementwise_exp10`. - For AMDPGU targets, added `__builtin_v_cvt_off_f32_i4` that maps to the `v_cvt_off_f32_i4` instruction. - Added `__builtin_elementwise_minnum` and `__builtin_elementwise_maxnum`. +- Added `__builtin_elementwise_minnumnum` and `__builtin_elementwise_maxnumnum`. - No longer crashing on invalid Objective-C categories and extensions when dumping the AST as JSON. (#GH137320) - Clang itself now uses split stacks instead of threads for allocating more @@ -674,7 +680,7 @@ Improvements to Clang's diagnostics #GH142457, #GH139913, #GH138850, #GH137867, #GH137860, #GH107840, #GH93308, #GH69470, #GH59391, #GH58172, #GH46215, #GH45915, #GH45891, #GH44490, #GH36703, #GH32903, #GH23312, #GH69874. - + - Clang no longer emits a spurious -Wdangling-gsl warning in C++23 when iterating over an element of a temporary container in a range-based for loop.(#GH109793, #GH145164) @@ -710,6 +716,12 @@ Improvements to Clang's diagnostics pointer, provided it can be proven that the pointer only points to ``[[noreturn]]`` functions. +- Added a separate diagnostic group ``-Wfunction-effect-redeclarations``, for the more pedantic + diagnostics for function effects (``[[clang::nonblocking]]`` and ``[[clang::nonallocating]]``). + Moved the warning for a missing (though implied) attribute on a redeclaration into this group. + Added a new warning in this group for the case where the attribute is missing/implicit on + an override of a virtual method. + Improvements to Clang's time-trace ---------------------------------- @@ -802,6 +814,11 @@ Bug Fixes in This Version nested scopes. (#GH147495) - Fixed a failed assertion with an operator call expression which comes from a macro expansion when performing analysis for nullability attributes. (#GH138371) +- Fixed a concept equivalent checking crash due to untransformed constraint expressions. (#GH146614) +- Fixed a crash in `clang-scan-deps` when a module with the same name is found + in different locations (#GH134404, #GH146976). +- Fix a crash when marco name is empty in ``#pragma push_macro("")`` or + ``#pragma pop_macro("")``. (GH149762). Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -970,6 +987,7 @@ Bug Fixes to C++ Support - Fixed a crash involving list-initialization of an empty class with a non-empty initializer list. (#GH147949) - Fixed constant evaluation of equality comparisons of constexpr-unknown references. (#GH147663) +- Diagnose binding a reference to ``*nullptr`` during constant evaluation. (#GH48665) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1199,6 +1217,8 @@ Static Analyzer --------------- - Fixed a crash when C++20 parenthesized initializer lists are used. This issue was causing a crash in clang-tidy. (#GH136041) +- The Clang Static Analyzer now handles parenthesized initialization. + (#GH148875) New features ^^^^^^^^^^^^ diff --git a/clang/docs/SanitizerSpecialCaseList.rst b/clang/docs/SanitizerSpecialCaseList.rst index 2c50778d0f491..194f2fc5a7825 100644 --- a/clang/docs/SanitizerSpecialCaseList.rst +++ b/clang/docs/SanitizerSpecialCaseList.rst @@ -39,6 +39,7 @@ Example void bad_foo() { int *a = (int*)malloc(40); a[10] = 1; + free(a); } int main() { bad_foo(); } $ cat ignorelist.txt diff --git a/clang/docs/StandardCPlusPlusModules.rst b/clang/docs/StandardCPlusPlusModules.rst index 933a57ff34dd9..31d0a5e769378 100644 --- a/clang/docs/StandardCPlusPlusModules.rst +++ b/clang/docs/StandardCPlusPlusModules.rst @@ -687,16 +687,12 @@ fails to instantiate. For such issues, users can add references to ``N::g`` in the `module purview `_ of ``M.cppm`` to ensure it is reachable, e.g. ``using N::g;``. -Support for Reduced BMIs is still experimental, but it may become the default -in the future. The expected roadmap for Reduced BMIs as of Clang 19.x is: - -1. ``-fexperimental-modules-reduced-bmi`` was introduced in v19.x -2. For v20.x, ``-fmodules-reduced-bmi`` is introduced as an equivalent non-experimental - option. It is expected to stay opt-in for 1~2 releases, though the period depends - on user feedback and may be extended. -3. Finally, ``-fmodules-reduced-bmi`` will be the default. When that time - comes, the term BMI will refer to the Reduced BMI and the Full BMI will only - be meaningful to build systems which elect to support two-phase compilation. +As of Clang 22.x, the Reduced BMI is enabled by default. You may still want to +use Full BMI with ``-fno-modules-reduced-bmi`` in the following case: +1. Your build system uses two-phase compilation but it haven't adjusted the +implementation for reduced BMI. +2. You meet a regression with Reduced BMI that you cannot work around. Please +report an issue for this case. Experimental Non-Cascading Changes ---------------------------------- diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 284a404026dfe..af0a8746d45e7 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -319,7 +319,7 @@ output format of the diagnostics that it generates. This option, which defaults to "none", controls whether or not Clang prints the category associated with a diagnostic when emitting it. - Each diagnostic may or many not have an associated category, if it + Each diagnostic may or may not have an associated category, if it has one, it is listed in the diagnostic categorization field of the diagnostic line (in the []'s). @@ -737,7 +737,7 @@ control the crash diagnostics. crash diagnostics files, but with lower precedence than the option. Clang is also capable of generating preprocessed source file(s) and associated -run script(s) even without a crash. This is specially useful when trying to +run script(s) even without a crash. This is especially useful when trying to generate a reproducer for warnings or errors while using modules. .. option:: -gen-reproducer @@ -1061,7 +1061,7 @@ In this way, the user may only need to specify a root configuration file with Usually, config file options are placed before command-line options, regardless of the actual operation to be performed. The exception is being made for the -options prefixed with the ``$`` character. These will be used only when linker +options prefixed with the ``$`` character. These will be used only when the linker is being invoked, and added after all of the command-line specified linker inputs. Here is some example of ``$``-prefixed options: @@ -1222,7 +1222,7 @@ existed. The push and pop pragmas will save and restore the full diagnostic state of the compiler, regardless of how it was set. It should be noted that while Clang supports the GCC pragma, Clang and GCC do not support the exact same set -of warnings, so even when using GCC compatible #pragmas there is no +of warnings, so even when using GCC-compatible #pragmas there is no guarantee that they will have identical behaviour on both compilers. Clang also doesn't yet support GCC behavior for ``#pragma diagnostic pop`` @@ -1681,7 +1681,7 @@ for more details. * ``preserve-sign`` - the sign of a flushed-to-zero number is preserved in the sign of 0 * ``positive-zero`` - denormals are flushed to positive zero - The default value depends on the target. For most targets, defaults to + The default value depends on the target. For most targets, it defaults to ``ieee``. .. option:: -f[no-]strict-float-cast-overflow @@ -1730,7 +1730,7 @@ for more details. the C and C++ standards but can be enabled using ``-ffp-contract=fast``. Fusion can be controlled with the ``FP_CONTRACT`` and ``clang fp contract`` - pragmas. Please note that pragmas will be ingored with + pragmas. Please note that pragmas will be ignored with ``-ffp-contract=fast``, and refer to the pragma documentation for a description of how the pragmas interact with the different ``-ffp-contract`` option values. @@ -1984,11 +1984,11 @@ for more details. call to runtime library functions (generally the case, but the BE might sometimes replace the library call if it knows enough about the potential range of the inputs). Overflow and non-finite values are handled by the - library implementation. For the case of multiplication overflow will occur in + library implementation. For the case of multiplication, overflow will occur in accordance with normal floating-point rules. This is the default value. * ``promoted`` Implementation of complex division using algebraic formulas at higher precision. Overflow is handled. Non-finite values are handled in some - cases. If the target does not have native support for a higher precision + cases. If the target does not have native support for a higher-precision data type, the implementation for the complex operation using the Smith algorithm will be used. Overflow may still occur in some cases. NaN and infinite values are not handled. diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index c35311c886413..be038d9165fc6 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -6953,6 +6953,21 @@ clang_getCursorUnaryOperatorKind(CXCursor cursor); * @} */ +/* CINDEX_DEPRECATED - disabled to silence MSVC deprecation warnings */ +typedef void *CXRemapping; + +CINDEX_DEPRECATED CINDEX_LINKAGE CXRemapping clang_getRemappings(const char *); + +CINDEX_DEPRECATED CINDEX_LINKAGE CXRemapping +clang_getRemappingsFromFileList(const char **, unsigned); + +CINDEX_DEPRECATED CINDEX_LINKAGE unsigned clang_remap_getNumFiles(CXRemapping); + +CINDEX_DEPRECATED CINDEX_LINKAGE void +clang_remap_getFilenames(CXRemapping, unsigned, CXString *, CXString *); + +CINDEX_DEPRECATED CINDEX_LINKAGE void clang_remap_dispose(CXRemapping); + LLVM_CLANG_C_EXTERN_C_END #endif diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 66ec3395571ea..17cbfb2693308 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -277,6 +277,11 @@ class ASTContext : public RefCountedBase { mutable llvm::ContextualFoldingSet ArrayParameterTypes; + /// Store the unique Type corresponding to each Kind. + mutable std::array + PredefinedSugarTypes{}; + /// The set of nested name specifiers. /// /// This set is managed by the NestedNameSpecifier class. @@ -1192,6 +1197,8 @@ class ASTContext : public RefCountedBase { bool isInSameModule(const Module *M1, const Module *M2) const; TranslationUnitDecl *getTranslationUnitDecl() const { + assert(TUDecl->getMostRecentDecl() == TUDecl && + "The active TU is not current one!"); return TUDecl->getMostRecentDecl(); } void addTranslationUnitDecl() { @@ -1567,6 +1574,8 @@ class ASTContext : public RefCountedBase { /// and bit count. QualType getDependentBitIntType(bool Unsigned, Expr *BitsExpr) const; + QualType getPredefinedSugarType(PredefinedSugarType::Kind KD) const; + /// Gets the struct used to keep track of the extended descriptor for /// pointer to blocks. QualType getBlockDescriptorExtendedType() const; @@ -1999,11 +2008,13 @@ class ASTContext : public RefCountedBase { /// . /// /// The sizeof operator requires this (C99 6.5.3.4p4). - CanQualType getSizeType() const; + QualType getSizeType() const; + + CanQualType getCanonicalSizeType() const; /// Return the unique signed counterpart of /// the integer type corresponding to size_t. - CanQualType getSignedSizeType() const; + QualType getSignedSizeType() const; /// Return the unique type for "intmax_t" (C99 7.18.1.5), defined in /// . diff --git a/clang/include/clang/AST/AbstractBasicReader.h b/clang/include/clang/AST/AbstractBasicReader.h index 514f4cef3a694..0a2db9e205c7c 100644 --- a/clang/include/clang/AST/AbstractBasicReader.h +++ b/clang/include/clang/AST/AbstractBasicReader.h @@ -269,12 +269,7 @@ class DataStreamBasicReader : public BasicReaderBase { case NestedNameSpecifier::Namespace: cur = NestedNameSpecifier::Create(ctx, cur, - asImpl().readNamespaceDeclRef()); - continue; - - case NestedNameSpecifier::NamespaceAlias: - cur = NestedNameSpecifier::Create(ctx, cur, - asImpl().readNamespaceAliasDeclRef()); + asImpl().readNamespaceBaseDeclRef()); continue; case NestedNameSpecifier::TypeSpec: diff --git a/clang/include/clang/AST/AbstractBasicWriter.h b/clang/include/clang/AST/AbstractBasicWriter.h index fedde8a2e46c5..c105bbbe45c92 100644 --- a/clang/include/clang/AST/AbstractBasicWriter.h +++ b/clang/include/clang/AST/AbstractBasicWriter.h @@ -251,11 +251,7 @@ class DataStreamBasicWriter : public BasicWriterBase { continue; case NestedNameSpecifier::Namespace: - asImpl().writeNamespaceDeclRef(NNS->getAsNamespace()); - continue; - - case NestedNameSpecifier::NamespaceAlias: - asImpl().writeNamespaceAliasDeclRef(NNS->getAsNamespaceAlias()); + asImpl().writeNamespaceBaseDeclRef(NNS->getAsNamespace()); continue; case NestedNameSpecifier::TypeSpec: diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index c75e29c861f82..08fe1f881503b 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -565,8 +565,28 @@ class LabelDecl : public NamedDecl { static bool classofKind(Kind K) { return K == Label; } }; +/// Represents C++ namespaces and their aliases. +/// +/// FIXME: Move `NamespaceBaseDecl` and `NamespaceDecl` to "DeclCXX.h" or +/// explain why not moving. +class NamespaceBaseDecl : public NamedDecl { +protected: + using NamedDecl::NamedDecl; + +public: + NamespaceDecl *getNamespace(); + const NamespaceDecl *getNamespace() const { + return const_cast(this)->getNamespace(); + } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { + return K >= firstNamespaceBase && K <= lastNamespaceBase; + } +}; + /// Represent a C++ namespace. -class NamespaceDecl : public NamedDecl, +class NamespaceDecl : public NamespaceBaseDecl, public DeclContext, public Redeclarable { /// The starting location of the source range, pointing diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 77bc3cad72ed9..33ae3d604020b 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -3186,7 +3186,7 @@ class UsingDirectiveDecl : public NamedDecl { /// \code /// namespace Foo = Bar; /// \endcode -class NamespaceAliasDecl : public NamedDecl, +class NamespaceAliasDecl : public NamespaceBaseDecl, public Redeclarable { friend class ASTDeclReader; @@ -3203,14 +3203,14 @@ class NamespaceAliasDecl : public NamedDecl, /// The Decl that this alias points to, either a NamespaceDecl or /// a NamespaceAliasDecl. - NamedDecl *Namespace; + NamespaceBaseDecl *Namespace; NamespaceAliasDecl(ASTContext &C, DeclContext *DC, SourceLocation NamespaceLoc, SourceLocation AliasLoc, IdentifierInfo *Alias, NestedNameSpecifierLoc QualifierLoc, - SourceLocation IdentLoc, NamedDecl *Namespace) - : NamedDecl(NamespaceAlias, DC, AliasLoc, Alias), redeclarable_base(C), - NamespaceLoc(NamespaceLoc), IdentLoc(IdentLoc), + SourceLocation IdentLoc, NamespaceBaseDecl *Namespace) + : NamespaceBaseDecl(NamespaceAlias, DC, AliasLoc, Alias), + redeclarable_base(C), NamespaceLoc(NamespaceLoc), IdentLoc(IdentLoc), QualifierLoc(QualifierLoc), Namespace(Namespace) {} void anchor() override; @@ -3222,13 +3222,11 @@ class NamespaceAliasDecl : public NamedDecl, NamespaceAliasDecl *getMostRecentDeclImpl() override; public: - static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation NamespaceLoc, - SourceLocation AliasLoc, - IdentifierInfo *Alias, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation IdentLoc, - NamedDecl *Namespace); + static NamespaceAliasDecl * + Create(ASTContext &C, DeclContext *DC, SourceLocation NamespaceLoc, + SourceLocation AliasLoc, IdentifierInfo *Alias, + NestedNameSpecifierLoc QualifierLoc, SourceLocation IdentLoc, + NamespaceBaseDecl *Namespace); static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID); @@ -3282,7 +3280,7 @@ class NamespaceAliasDecl : public NamedDecl, /// Retrieve the namespace that this alias refers to, which /// may either be a NamespaceDecl or a NamespaceAliasDecl. - NamedDecl *getAliasedNamespace() const { return Namespace; } + NamespaceBaseDecl *getAliasedNamespace() const { return Namespace; } SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(NamespaceLoc, IdentLoc); diff --git a/clang/include/clang/AST/FormatString.h b/clang/include/clang/AST/FormatString.h index 3560766433fe2..a284f2c44d633 100644 --- a/clang/include/clang/AST/FormatString.h +++ b/clang/include/clang/AST/FormatString.h @@ -489,7 +489,8 @@ class FormatSpecifier { /// For a TypedefType QT, if it is a named integer type such as size_t, /// assign the appropriate value to LM and return true. - static bool namedTypeToLengthModifier(QualType QT, LengthModifier &LM); + static bool namedTypeToLengthModifier(ASTContext &Ctx, QualType QT, + LengthModifier &LM); }; } // end analyze_format_string namespace diff --git a/clang/include/clang/AST/NestedNameSpecifier.h b/clang/include/clang/AST/NestedNameSpecifier.h index 952c79753d10a..1614f9d7c94e4 100644 --- a/clang/include/clang/AST/NestedNameSpecifier.h +++ b/clang/include/clang/AST/NestedNameSpecifier.h @@ -31,8 +31,7 @@ class ASTContext; class CXXRecordDecl; class IdentifierInfo; class LangOptions; -class NamespaceAliasDecl; -class NamespaceDecl; +class NamespaceBaseDecl; struct PrintingPolicy; class Type; class TypeLoc; @@ -79,12 +78,9 @@ class NestedNameSpecifier : public llvm::FoldingSetNode { /// An identifier, stored as an IdentifierInfo*. Identifier, - /// A namespace, stored as a NamespaceDecl*. + /// A namespace-like entity, stored as a NamespaceBaseDecl*. Namespace, - /// A namespace alias, stored as a NamespaceAliasDecl*. - NamespaceAlias, - /// A type, stored as a Type*. TypeSpec, @@ -121,15 +117,10 @@ class NestedNameSpecifier : public llvm::FoldingSetNode { NestedNameSpecifier *Prefix, const IdentifierInfo *II); - /// Builds a nested name specifier that names a namespace. - static NestedNameSpecifier *Create(const ASTContext &Context, - NestedNameSpecifier *Prefix, - const NamespaceDecl *NS); - - /// Builds a nested name specifier that names a namespace alias. + /// Builds a nested name specifier that names a namespace or namespace alias. static NestedNameSpecifier *Create(const ASTContext &Context, NestedNameSpecifier *Prefix, - const NamespaceAliasDecl *Alias); + const NamespaceBaseDecl *NS); /// Builds a nested name specifier that names a type. static NestedNameSpecifier * @@ -174,13 +165,9 @@ class NestedNameSpecifier : public llvm::FoldingSetNode { return nullptr; } - /// Retrieve the namespace stored in this nested name + /// Retrieve the namespace or namespace alias stored in this nested name /// specifier. - NamespaceDecl *getAsNamespace() const; - - /// Retrieve the namespace alias stored in this nested name - /// specifier. - NamespaceAliasDecl *getAsNamespaceAlias() const; + NamespaceBaseDecl *getAsNamespace() const; /// Retrieve the record declaration stored in this nested name /// specifier. @@ -425,29 +412,15 @@ class NestedNameSpecifierLocBuilder { /// \param Context The AST context in which this nested-name-specifier /// resides. /// - /// \param Namespace The namespace. + /// \param Namespace The namespace or namespace alias. /// - /// \param NamespaceLoc The location of the namespace name. + /// \param NamespaceLoc The location of the namespace name or the namespace + // alias. /// /// \param ColonColonLoc The location of the trailing '::'. - void Extend(ASTContext &Context, NamespaceDecl *Namespace, + void Extend(ASTContext &Context, NamespaceBaseDecl *Namespace, SourceLocation NamespaceLoc, SourceLocation ColonColonLoc); - /// Extend the current nested-name-specifier by another - /// nested-name-specifier component of the form 'namespace-alias::'. - /// - /// \param Context The AST context in which this nested-name-specifier - /// resides. - /// - /// \param Alias The namespace alias. - /// - /// \param AliasLoc The location of the namespace alias - /// name. - /// - /// \param ColonColonLoc The location of the trailing '::'. - void Extend(ASTContext &Context, NamespaceAliasDecl *Alias, - SourceLocation AliasLoc, SourceLocation ColonColonLoc); - /// Turn this (empty) nested-name-specifier into the global /// nested-name-specifier '::'. void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td index 1215056ffde1b..0438e4dfbafac 100644 --- a/clang/include/clang/AST/PropertiesBase.td +++ b/clang/include/clang/AST/PropertiesBase.td @@ -91,6 +91,7 @@ def DeclRef : RefPropertyType<"Decl"> { let ConstWhenWriting = 1; } SubclassPropertyType<"FunctionDecl", DeclRef>; def NamedDeclRef : SubclassPropertyType<"NamedDecl", DeclRef>; + def NamespaceBaseDeclRef : SubclassPropertyType<"NamespaceBaseDecl", DeclRef>; def NamespaceDeclRef : SubclassPropertyType<"NamespaceDecl", DeclRef>; def NamespaceAliasDeclRef : diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 5cb2f57edffe4..62991d986e675 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -789,7 +789,6 @@ bool RecursiveASTVisitor::TraverseNestedNameSpecifier( switch (NNS->getKind()) { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: case NestedNameSpecifier::Super: return true; @@ -813,7 +812,6 @@ bool RecursiveASTVisitor::TraverseNestedNameSpecifierLoc( switch (NNS.getNestedNameSpecifier()->getKind()) { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: case NestedNameSpecifier::Super: return true; @@ -1210,6 +1208,8 @@ DEF_TRAVERSE_TYPE(BitIntType, {}) DEF_TRAVERSE_TYPE(DependentBitIntType, { TRY_TO(TraverseStmt(T->getNumBitsExpr())); }) +DEF_TRAVERSE_TYPE(PredefinedSugarType, {}) + #undef DEF_TRAVERSE_TYPE // ----------------- TypeLoc traversal ----------------- @@ -1526,6 +1526,8 @@ DEF_TRAVERSE_TYPELOC(DependentBitIntType, { TRY_TO(TraverseStmt(TL.getTypePtr()->getNumBitsExpr())); }) +DEF_TRAVERSE_TYPELOC(PredefinedSugarType, {}) + #undef DEF_TRAVERSE_TYPELOC // ----------------- Decl traversal ----------------- diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 21b97102db95a..764e9d508a25a 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -2258,6 +2258,30 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { unsigned NumExpansions; }; + enum class PredefinedSugarKind { + /// The "size_t" type. + SizeT, + + /// The signed integer type corresponding to "size_t". + SignedSizeT, + + /// The "ptrdiff_t" type. + PtrdiffT, + + // Indicates how many items the enum has. + Last = PtrdiffT + }; + + class PresefinedSugarTypeBitfields { + friend class PredefinedSugarType; + + LLVM_PREFERRED_TYPE(TypeBitfields) + unsigned : NumTypeBits; + + LLVM_PREFERRED_TYPE(PredefinedSugarKind) + unsigned Kind : 8; + }; + class CountAttributedTypeBitfields { friend class CountAttributedType; @@ -2297,6 +2321,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { DependentTemplateSpecializationTypeBits; PackExpansionTypeBitfields PackExpansionTypeBits; CountAttributedTypeBitfields CountAttributedTypeBits; + PresefinedSugarTypeBitfields PredefinedSugarTypeBits; }; private: @@ -8038,6 +8063,37 @@ class DependentBitIntType final : public Type, public llvm::FoldingSetNode { } }; +class PredefinedSugarType final : public Type { +public: + friend class ASTContext; + using Kind = PredefinedSugarKind; + +private: + PredefinedSugarType(Kind KD, const IdentifierInfo *IdentName, + QualType CanonicalType) + : Type(PredefinedSugar, CanonicalType, TypeDependence::None), + Name(IdentName) { + PredefinedSugarTypeBits.Kind = llvm::to_underlying(KD); + } + + static StringRef getName(Kind KD); + + const IdentifierInfo *Name; + +public: + bool isSugared() const { return true; } + + QualType desugar() const { return getCanonicalTypeInternal(); } + + Kind getKind() const { return Kind(PredefinedSugarTypeBits.Kind); } + + const IdentifierInfo *getIdentifier() const { return Name; } + + static bool classof(const Type *T) { + return T->getTypeClass() == PredefinedSugar; + } +}; + /// A qualifier set is used to build a set of qualifiers. class QualifierCollector : public Qualifiers { public: diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h index cf06e27758996..be0bc896de3ea 100644 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -2783,6 +2783,16 @@ class ObjCProtocolLoc { } }; +struct PredefinedSugarTypeLocInfo {}; // Nothing. + +class PredefinedSugarTypeLoc final + : public ConcreteTypeLoc { +public: + void initializeLocal(ASTContext &Context, SourceLocation loc) {} + SourceRange getLocalSourceRange() const { return {}; } +}; + } // namespace clang #endif // LLVM_CLANG_AST_TYPELOC_H diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td index a6157649060b1..3114d1180319a 100644 --- a/clang/include/clang/AST/TypeProperties.td +++ b/clang/include/clang/AST/TypeProperties.td @@ -1028,3 +1028,12 @@ let Class = DependentBitIntType in { return ctx.getDependentBitIntType(isUnsigned, numBitsExpr); }]>; } + +let Class = PredefinedSugarType in { + def : Property<"kind", UInt32> { + let Read = [{ static_cast(node->getKind()) }]; + } + def : Creator<[{ + return ctx.getPredefinedSugarType(static_cast(kind)); + }]>; +} diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index b364b6556d0b3..08c898f7758ec 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -7894,9 +7894,9 @@ AST_MATCHER_P_OVERLOAD(NestedNameSpecifierLoc, hasPrefix, /// matches "ns::" AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace, internal::Matcher, InnerMatcher) { - if (!Node.getAsNamespace()) - return false; - return InnerMatcher.matches(*Node.getAsNamespace(), Finder, Builder); + if (auto *NS = dyn_cast_if_present(Node.getAsNamespace())) + return InnerMatcher.matches(*NS, Finder, Builder); + return false; } /// Matches attributes. diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety.h index 9998702a41cab..beeb0aaba5d0d 100644 --- a/clang/include/clang/Analysis/Analyses/LifetimeSafety.h +++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety.h @@ -17,14 +17,96 @@ //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H #define LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H -#include "clang/AST/DeclBase.h" #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" -namespace clang { +#include "llvm/ADT/ImmutableSet.h" +#include "llvm/ADT/StringMap.h" +#include -void runLifetimeSafetyAnalysis(const DeclContext &DC, const CFG &Cfg, - AnalysisDeclContext &AC); +namespace clang::lifetimes { -} // namespace clang +/// The main entry point for the analysis. +void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC); + +namespace internal { +// Forward declarations of internal types. +class Fact; +class FactManager; +class LoanPropagationAnalysis; +struct LifetimeFactory; + +/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type. +/// Used for giving ID to loans and origins. +template struct ID { + uint32_t Value = 0; + + bool operator==(const ID &Other) const { return Value == Other.Value; } + bool operator!=(const ID &Other) const { return !(*this == Other); } + bool operator<(const ID &Other) const { return Value < Other.Value; } + ID operator++(int) { + ID Tmp = *this; + ++Value; + return Tmp; + } + void Profile(llvm::FoldingSetNodeID &IDBuilder) const { + IDBuilder.AddInteger(Value); + } +}; + +using LoanID = ID; +using OriginID = ID; + +// Using LLVM's immutable collections is efficient for dataflow analysis +// as it avoids deep copies during state transitions. +// TODO(opt): Consider using a bitset to represent the set of loans. +using LoanSet = llvm::ImmutableSet; +using OriginSet = llvm::ImmutableSet; + +/// A `ProgramPoint` identifies a location in the CFG by pointing to a specific +/// `Fact`. identified by a lifetime-related event (`Fact`). +/// +/// A `ProgramPoint` has "after" semantics: it represents the location +/// immediately after its corresponding `Fact`. +using ProgramPoint = const Fact *; + +/// Running the lifetime safety analysis and querying its results. It +/// encapsulates the various dataflow analyses. +class LifetimeSafetyAnalysis { +public: + LifetimeSafetyAnalysis(AnalysisDeclContext &AC); + ~LifetimeSafetyAnalysis(); + + void run(); + + /// Returns the set of loans an origin holds at a specific program point. + LoanSet getLoansAtPoint(OriginID OID, ProgramPoint PP) const; + + /// Finds the OriginID for a given declaration. + /// Returns a null optional if not found. + std::optional getOriginIDForDecl(const ValueDecl *D) const; + + /// Finds the LoanID's for the loan created with the specific variable as + /// their Path. + std::vector getLoanIDForVar(const VarDecl *VD) const; + + /// Retrieves program points that were specially marked in the source code + /// for testing. + /// + /// The analysis recognizes special function calls of the form + /// `void("__lifetime_test_point_")` as test points. This method returns + /// a map from the annotation string () to the corresponding + /// `ProgramPoint`. This allows test harnesses to query the analysis state at + /// user-defined locations in the code. + /// \note This is intended for testing only. + llvm::StringMap getTestPoints() const; + +private: + AnalysisDeclContext &AC; + std::unique_ptr Factory; + std::unique_ptr FactMgr; + std::unique_ptr LoanPropagation; +}; +} // namespace internal +} // namespace clang::lifetimes #endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 5ebb82180521d..c81714e9b009d 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -1334,6 +1334,18 @@ def ElementwiseMinimum : Builtin { let Prototype = "void(...)"; } +def ElementwiseMaximumNum : Builtin { + let Spellings = ["__builtin_elementwise_maximumnum"]; + let Attributes = [NoThrow, Const, CustomTypeChecking]; + let Prototype = "void(...)"; +} + +def ElementwiseMinimumNum : Builtin { + let Spellings = ["__builtin_elementwise_minimumnum"]; + let Attributes = [NoThrow, Const, CustomTypeChecking]; + let Prototype = "void(...)"; +} + def ElementwiseCeil : Builtin { let Spellings = ["__builtin_elementwise_ceil"]; let Attributes = [NoThrow, Const, CustomTypeChecking]; diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def b/clang/include/clang/Basic/BuiltinsAMDGPU.def index 29e1e99bba9ef..878543566f0e3 100644 --- a/clang/include/clang/Basic/BuiltinsAMDGPU.def +++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def @@ -164,6 +164,7 @@ BUILTIN(__builtin_amdgcn_raw_buffer_load_b96, "V3UiQbiiIi", "n") BUILTIN(__builtin_amdgcn_raw_buffer_load_b128, "V4UiQbiiIi", "n") TARGET_BUILTIN(__builtin_amdgcn_raw_ptr_buffer_load_lds, "vQbv*3IUiiiIiIi", "t", "vmem-to-lds-load-insts") +TARGET_BUILTIN(__builtin_amdgcn_struct_ptr_buffer_load_lds, "vQbv*3IUiiiiIiIi", "t", "vmem-to-lds-load-insts") //===----------------------------------------------------------------------===// // Ballot builtins. @@ -668,13 +669,23 @@ TARGET_BUILTIN(__builtin_amdgcn_s_monitor_sleep, "vIs", "n", "gfx1250-insts") TARGET_BUILTIN(__builtin_amdgcn_s_wait_asynccnt, "vIUs", "n", "gfx1250-insts") TARGET_BUILTIN(__builtin_amdgcn_s_wait_tensorcnt, "vIUs", "n", "gfx1250-insts") +TARGET_BUILTIN(__builtin_amdgcn_tanhf, "ff", "nc", "tanh-insts") +TARGET_BUILTIN(__builtin_amdgcn_tanhh, "hh", "nc", "tanh-insts") TARGET_BUILTIN(__builtin_amdgcn_tanh_bf16, "yy", "nc", "bf16-trans-insts") TARGET_BUILTIN(__builtin_amdgcn_rcp_bf16, "yy", "nc", "bf16-trans-insts") +TARGET_BUILTIN(__builtin_amdgcn_sqrt_bf16, "yy", "nc", "bf16-trans-insts") +TARGET_BUILTIN(__builtin_amdgcn_rsq_bf16, "yy", "nc", "bf16-trans-insts") +TARGET_BUILTIN(__builtin_amdgcn_log_bf16, "yy", "nc", "bf16-trans-insts") +TARGET_BUILTIN(__builtin_amdgcn_exp2_bf16, "yy", "nc", "bf16-trans-insts") +TARGET_BUILTIN(__builtin_amdgcn_sin_bf16, "yy", "nc", "bf16-trans-insts") +TARGET_BUILTIN(__builtin_amdgcn_cos_bf16, "yy", "nc", "bf16-trans-insts") TARGET_BUILTIN(__builtin_amdgcn_cvt_f16_fp8, "hiIi", "nc", "gfx1250-insts") TARGET_BUILTIN(__builtin_amdgcn_cvt_f16_bf8, "hiIi", "nc", "gfx1250-insts") TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_f16_fp8, "V2hs", "nc", "gfx1250-insts") TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_f16_bf8, "V2hs", "nc", "gfx1250-insts") +TARGET_BUILTIN(__builtin_amdgcn_sat_pk4_i4_i8, "UsUi", "nc", "gfx1250-insts") +TARGET_BUILTIN(__builtin_amdgcn_sat_pk4_u4_u8, "UsUi", "nc", "gfx1250-insts") // GFX1250 WMMA builtins TARGET_BUILTIN(__builtin_amdgcn_wmma_f32_16x16x4_f32, "V8fIbV2fIbV2fIsV8fIbIb", "nc", "gfx1250-insts,wavefrontsize32") @@ -694,6 +705,7 @@ TARGET_BUILTIN(__builtin_amdgcn_wmma_f16_16x16x128_fp8_fp8, "V8hV16iV16iIsV8hIbI TARGET_BUILTIN(__builtin_amdgcn_wmma_f16_16x16x128_fp8_bf8, "V8hV16iV16iIsV8hIbIb", "nc", "gfx1250-insts,wavefrontsize32") TARGET_BUILTIN(__builtin_amdgcn_wmma_f16_16x16x128_bf8_fp8, "V8hV16iV16iIsV8hIbIb", "nc", "gfx1250-insts,wavefrontsize32") TARGET_BUILTIN(__builtin_amdgcn_wmma_f16_16x16x128_bf8_bf8, "V8hV16iV16iIsV8hIbIb", "nc", "gfx1250-insts,wavefrontsize32") +TARGET_BUILTIN(__builtin_amdgcn_wmma_f32_16x16x128_f8f6f4, "V8fIiV16iIiV16iIsV8f", "nc", "gfx1250-insts,wavefrontsize32") TARGET_BUILTIN(__builtin_amdgcn_wmma_f32_16x16x128_fp8_fp8, "V8fV16iV16iIsV8fIbIb", "nc", "gfx1250-insts,wavefrontsize32") TARGET_BUILTIN(__builtin_amdgcn_wmma_f32_16x16x128_fp8_bf8, "V8fV16iV16iIsV8fIbIb", "nc", "gfx1250-insts,wavefrontsize32") TARGET_BUILTIN(__builtin_amdgcn_wmma_f32_16x16x128_bf8_fp8, "V8fV16iV16iIsV8fIbIb", "nc", "gfx1250-insts,wavefrontsize32") diff --git a/clang/include/clang/Basic/BuiltinsSPIRVVK.td b/clang/include/clang/Basic/BuiltinsSPIRVVK.td index 61cc0343c415e..5dc3c7588cd2a 100644 --- a/clang/include/clang/Basic/BuiltinsSPIRVVK.td +++ b/clang/include/clang/Basic/BuiltinsSPIRVVK.td @@ -11,3 +11,4 @@ include "clang/Basic/BuiltinsSPIRVBase.td" def reflect : SPIRVBuiltin<"void(...)", [NoThrow, Const]>; def faceforward : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>; +def refract : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>; diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index a11e12d495cd2..cfffeb71f09d1 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -56,6 +56,8 @@ CODEGENOPT(XCOFFReadOnlyPointers, 1, 0, Benign) ///< Set for -mxcoff-roptr. CODEGENOPT(AllTocData, 1, 0, Benign) ///< AIX -mtocdata ENUM_CODEGENOPT(FramePointer, FramePointerKind, 2, FramePointerKind::None, Benign) /// frame-pointer: all,non-leaf,reserved,none +ENUM_CODEGENOPT(ExceptionHandling, ExceptionHandlingKind, 3, ExceptionHandlingKind::None, NotCompatible) + CODEGENOPT(ClearASTBeforeBackend , 1, 0, Benign) ///< Free the AST before running backend code generation. Only works with -disable-free. CODEGENOPT(DisableFree , 1, 0, Benign) ///< Don't free memory. CODEGENOPT(DiscardValueNames , 1, 0, Benign) ///< Discard Value Names from the IR (LLVMContext flag) diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index df4403ace5fe3..cdeedd5b4eac6 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -176,6 +176,9 @@ class CodeGenOptions : public CodeGenOptionsBase { llvm_unreachable("invalid FramePointerKind"); } + /// Possible exception handling behavior. + enum class ExceptionHandlingKind { None, SjLj, WinEH, DwarfCFI, Wasm }; + enum class SwiftAsyncFramePointerKind { Auto, // Choose Swift async extended frame info based on deployment target. Always, // Unconditionally emit Swift async extended frame info. @@ -552,6 +555,22 @@ class CodeGenOptions : public CodeGenOptionsBase { return NoBuiltinFuncs; } + bool hasSjLjExceptions() const { + return getExceptionHandling() == ExceptionHandlingKind::SjLj; + } + + bool hasSEHExceptions() const { + return getExceptionHandling() == ExceptionHandlingKind::WinEH; + } + + bool hasDWARFExceptions() const { + return getExceptionHandling() == ExceptionHandlingKind::DwarfCFI; + } + + bool hasWasmExceptions() const { + return getExceptionHandling() == ExceptionHandlingKind::Wasm; + } + /// Check if Clang profile instrumenation is on. bool hasProfileClangInstr() const { return getProfileInstr() == diff --git a/clang/include/clang/Basic/DeclNodes.td b/clang/include/clang/Basic/DeclNodes.td index f1ebaf1db3fc0..8d6731b50f509 100644 --- a/clang/include/clang/Basic/DeclNodes.td +++ b/clang/include/clang/Basic/DeclNodes.td @@ -15,9 +15,10 @@ def PragmaComment : DeclNode; def PragmaDetectMismatch : DeclNode; def ExternCContext : DeclNode, DeclContext; def Named : DeclNode; - def Namespace : DeclNode, DeclContext; + def NamespaceBase : DeclNode; + def Namespace : DeclNode, DeclContext; + def NamespaceAlias : DeclNode; def UsingDirective : DeclNode; - def NamespaceAlias : DeclNode; def Label : DeclNode; def Type : DeclNode; def TypedefName : DeclNode; diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h index c7a627600f3cc..cee5bed665d0a 100644 --- a/clang/include/clang/Basic/Diagnostic.h +++ b/clang/include/clang/Basic/Diagnostic.h @@ -895,7 +895,10 @@ class DiagnosticsEngine : public RefCountedBase { /// \param FormatString A fixed diagnostic format string that will be hashed /// and mapped to a unique DiagID. template - // TODO: Deprecate this once all uses are removed from Clang. + // FIXME: this API should almost never be used; custom diagnostics do not + // have an associated diagnostic group and thus cannot be controlled by users + // like other diagnostics. The number of times this API is used in Clang + // should only ever be reduced, not increased. // [[deprecated("Use a CustomDiagDesc instead of a Level")]] unsigned getCustomDiagID(Level L, const char (&FormatString)[N]) { return Diags->getCustomDiagID((DiagnosticIDs::Level)L, diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index a67b9995d3b54..071a38f513911 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -174,10 +174,11 @@ def note_constexpr_heap_alloc_limit_exceeded : Note< def note_constexpr_this : Note< "%select{|implicit }0use of 'this' pointer is only allowed within the " "evaluation of a call to a 'constexpr' member function">; -def access_kind : TextSubstitution< - "%select{read of|read of|assignment to|increment of|decrement of|" - "member call on|dynamic_cast of|typeid applied to|construction of|" - "destruction of|read of}0">; +def access_kind + : TextSubstitution< + "%select{read of|read of|assignment to|increment of|decrement of|" + "member call on|dynamic_cast of|typeid applied to|construction of|" + "destruction of|read of|read of}0">; def access_kind_subobject : TextSubstitution< "%select{read of|read of|assignment to|increment of|decrement of|" "member call on|dynamic_cast of|typeid applied to|" @@ -222,6 +223,9 @@ def note_constexpr_ltor_incomplete_type : Note< def note_constexpr_access_null : Note< "%sub{access_kind}0 " "dereferenced null pointer is not allowed in a constant expression">; +def note_constexpr_dereferencing_null + : Note<"dereferencing a null pointer is not allowed in a constant " + "expression">; def note_constexpr_access_past_end : Note< "%sub{access_kind}0 dereferenced one-past-the-end pointer " "is not allowed in a constant expression">; diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 34b6c0d7a8acd..759ba0419bd45 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -116,6 +116,8 @@ def err_drv_cuda_host_arch : Error< "unsupported architecture '%0' for host compilation">; def err_drv_mix_cuda_hip : Error< "mixed CUDA and HIP compilation is not supported">; +def err_drv_mix_offload : Error< + "mixed %0 and %1 offloading compilation is not supported">; def err_drv_bad_target_id : Error< "invalid target ID '%0'; format is a processor name followed by an optional " "colon-delimited list of features followed by an enable/disable sign (e.g., " diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index c28a919e35d08..ccb18aa37447e 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1293,6 +1293,7 @@ def ThreadSafetyBeta : DiagGroup<"thread-safety-beta">; // Warnings and notes related to the function effects system which underlies // the nonblocking and nonallocating attributes. def FunctionEffects : DiagGroup<"function-effects">; +def FunctionEffectRedeclarations : DiagGroup<"function-effect-redeclarations">; def PerfConstraintImpliesNoexcept : DiagGroup<"perf-constraint-implies-noexcept">; // Uniqueness Analysis warnings diff --git a/clang/include/clang/Basic/DiagnosticIDs.h b/clang/include/clang/Basic/DiagnosticIDs.h index 2b095f0fd6741..f07a003f3fdef 100644 --- a/clang/include/clang/Basic/DiagnosticIDs.h +++ b/clang/include/clang/Basic/DiagnosticIDs.h @@ -283,7 +283,10 @@ class DiagnosticIDs : public RefCountedBase { // writing, nearly all callers of this function were invalid. unsigned getCustomDiagID(CustomDiagDesc Diag); - // TODO: Deprecate this once all uses are removed from LLVM + // FIXME: this API should almost never be used; custom diagnostics do not + // have an associated diagnostic group and thus cannot be controlled by users + // like other diagnostics. The number of times this API is used in Clang + // should only ever be reduced, not increased. // [[deprecated("Use a CustomDiagDesc instead of a Level")]] unsigned getCustomDiagID(Level Level, StringRef Message) { return getCustomDiagID([&]() -> CustomDiagDesc { diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td index 723f5d48b4f5f..c7fe6e1db6d1f 100644 --- a/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -694,6 +694,9 @@ def err_pragma_push_pop_macro_malformed : Error< def warn_pragma_pop_macro_no_push : Warning< "pragma pop_macro could not pop '%0', no matching push_macro">, InGroup; +def warn_pargma_push_pop_macro_empty_string : Warning< + "'#pragma %select{push_macro|pop_macro}0' expected a non-empty string">, + InGroup; def warn_pragma_message : Warning<"%0">, InGroup, DefaultWarnNoWerror; def err_pragma_message : Error<"%0">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 2781ff81ab4cf..b2ea65ae111be 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11530,17 +11530,28 @@ def note_in_evaluating_default_argument : Note< def warn_invalid_add_func_effects : Warning< "attribute '%0' should not be added via type conversion">, InGroup, DefaultIgnore; -def warn_mismatched_func_effect_override : Warning< - "attribute '%0' on overriding function does not match base declaration">, - InGroup, DefaultIgnore; -def warn_mismatched_func_effect_redeclaration : Warning< - "attribute '%0' on function does not match previous declaration">, - InGroup, DefaultIgnore; +def warn_conflicting_func_effect_override + : Warning<"attribute '%0' on overriding function conflicts with base " + "declaration">, + InGroup, + DefaultIgnore; def warn_conflicting_func_effects : Warning< "effects conflict when merging declarations; kept '%0', discarded '%1'">, InGroup, DefaultIgnore; def err_func_with_effects_no_prototype : Error< "'%0' function must have a prototype">; +// These are more pedantic: in redeclarations and virtual method overrides, +// the effect attribute(s) should be restated. +def warn_mismatched_func_effect_override + : Warning<"overriding function is missing '%0' attribute from base " + "declaration">, + InGroup, + DefaultIgnore; +def warn_mismatched_func_effect_redeclaration + : Warning< + "redeclaration is missing '%0' attribute from previous declaration">, + InGroup, + DefaultIgnore; } // end of sema category @@ -12357,7 +12368,7 @@ def err_export_using_internal : Error< "using declaration referring to %1 with %select{internal|module|unknown}0 " "linkage cannot be exported">; def err_export_not_in_module_interface : Error< - "export declaration can only be used within a module purview">; + "export declaration can only be used within a module interface">; def err_export_inline_not_defined : Error< "inline function not defined%select{| before the private module fragment}0">; def err_export_partition_impl : Error< @@ -13478,6 +13489,12 @@ def err_acc_invalid_default_type def err_acc_device_type_multiple_archs : Error<"OpenACC 'device_type' clause on a 'set' construct only permits " "one architecture">; +def warn_acc_var_referenced_lacks_op + : Warning<"variable of type %0 referenced in OpenACC '%1' clause does not " + "have a %enum_select{%DefCtor{default " + "constructor}|%Dtor{destructor}}2; reference has no effect">, + InGroup>, + DefaultError; // AMDGCN builtins diagnostics def err_amdgcn_load_lds_size_invalid_value : Error<"invalid size value">; diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 6c47107796236..08d98a77e0252 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -98,8 +98,6 @@ LANGOPT(Exceptions , 1, 0, NotCompatible, "exception handling") LANGOPT(ObjCExceptions , 1, 0, NotCompatible, "Objective-C exceptions") LANGOPT(CXXExceptions , 1, 0, NotCompatible, "C++ exceptions") LANGOPT(EHAsynch , 1, 0, NotCompatible, "C/C++ EH Asynch exceptions") -ENUM_LANGOPT(ExceptionHandling, ExceptionHandlingKind, 3, - ExceptionHandlingKind::None, NotCompatible, "exception handling") LANGOPT(IgnoreExceptions , 1, 0, NotCompatible, "ignore exceptions") LANGOPT(ExternCNoUnwind , 1, 0, NotCompatible, "Assume extern C functions don't unwind") LANGOPT(AssumeNothrowExceptionDtor , 1, 0, NotCompatible, "Assume exception object's destructor is nothrow") @@ -493,6 +491,8 @@ LANGOPT(CheckConstexprFunctionBodies, 1, 1, Benign, LANGOPT(BoundsSafety, 1, 0, NotCompatible, "Bounds safety extension for C") +LANGOPT(EnableLifetimeSafety, 1, 0, NotCompatible, "Experimental lifetime safety analysis for C++") + LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector type") #undef LANGOPT diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 4c642c9e10c91..0407897359b5e 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -337,9 +337,6 @@ class LangOptionsBase { enum ExcessPrecisionKind { FPP_Standard, FPP_Fast, FPP_None }; - /// Possible exception handling behavior. - enum class ExceptionHandlingKind { None, SjLj, WinEH, DwarfCFI, Wasm }; - enum class LaxVectorConversionKind { /// Permit no implicit vector bitcasts. None, @@ -636,11 +633,6 @@ class LangOptions : public LangOptionsBase { // received as a result of a standard operator new (-fcheck-new) bool CheckNew = false; - // In OpenACC mode, contains a user provided override for the _OPENACC macro. - // This exists so that we can override the macro value and test our incomplete - // implementation on real-world examples. - std::string OpenACCMacroOverride; - /// The HLSL root signature version for dxil. llvm::dxbc::RootSignatureVersion HLSLRootSigVer = llvm::dxbc::RootSignatureVersion::V1_1; @@ -788,22 +780,6 @@ class LangOptions : public LangOptionsBase { return getSignReturnAddressScope() == SignReturnAddressScopeKind::All; } - bool hasSjLjExceptions() const { - return getExceptionHandling() == ExceptionHandlingKind::SjLj; - } - - bool hasSEHExceptions() const { - return getExceptionHandling() == ExceptionHandlingKind::WinEH; - } - - bool hasDWARFExceptions() const { - return getExceptionHandling() == ExceptionHandlingKind::DwarfCFI; - } - - bool hasWasmExceptions() const { - return getExceptionHandling() == ExceptionHandlingKind::Wasm; - } - bool isSYCL() const { return SYCLIsDevice || SYCLIsHost; } bool hasDefaultVisibilityExportMapping() const { diff --git a/clang/include/clang/Basic/TypeNodes.td b/clang/include/clang/Basic/TypeNodes.td index 567b8a5ca5a4d..971ce541d4831 100644 --- a/clang/include/clang/Basic/TypeNodes.td +++ b/clang/include/clang/Basic/TypeNodes.td @@ -117,3 +117,4 @@ def PipeType : TypeNode; def AtomicType : TypeNode; def BitIntType : TypeNode; def DependentBitIntType : TypeNode, AlwaysDependent; +def PredefinedSugarType : TypeNode, NeverCanonical; diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index 277c278fd38b7..25baf278bba38 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -129,6 +129,22 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { cir::BoolAttr getTrueAttr() { return getCIRBoolAttr(true); } cir::BoolAttr getFalseAttr() { return getCIRBoolAttr(false); } + mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real, + mlir::Value imag) { + auto resultComplexTy = cir::ComplexType::get(real.getType()); + return create(loc, resultComplexTy, real, imag); + } + + mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand) { + auto operandTy = mlir::cast(operand.getType()); + return create(loc, operandTy.getElementType(), operand); + } + + mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand) { + auto operandTy = mlir::cast(operand.getType()); + return create(loc, operandTy.getElementType(), operand); + } + mlir::Value createNot(mlir::Value value) { return create(value.getLoc(), value.getType(), cir::UnaryOpKind::Not, value); @@ -169,6 +185,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { return create(loc); } + mlir::Value createUnaryOp(mlir::Location loc, cir::UnaryOpKind kind, + mlir::Value operand) { + return create(loc, kind, operand); + } + mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value) { return cir::ConstPtrAttr::get(type, getI64IntegerAttr(value)); } diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 2ce23dbb27ec6..694e3691c9361 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -1739,7 +1739,8 @@ def CIR_SetBitfieldOp : CIR_Op<"set_bitfield"> { %2 = cir.load %0 : !cir.ptr>, !cir.ptr %3 = cir.get_member %2[1] {name = "e"} : !cir.ptr -> !cir.ptr - %4 = cir.set_bitfield(#bfi_e, %3 : !cir.ptr, %1 : !s32i) -> !s32i + %4 = cir.set_bitfield align(4) (#bfi_e, %3 : !cir.ptr, %1 : !s32i) + -> !s32i ``` }]; @@ -1747,12 +1748,15 @@ def CIR_SetBitfieldOp : CIR_Op<"set_bitfield"> { Arg:$addr, CIR_AnyType:$src, BitfieldInfoAttr:$bitfield_info, + DefaultValuedOptionalAttr:$alignment, UnitAttr:$is_volatile ); let results = (outs CIR_IntType:$result); - let assemblyFormat = [{ `(`$bitfield_info`,` $addr`:`qualified(type($addr))`,` + let assemblyFormat = [{ + (`align` `(` $alignment^ `)`)? + `(`$bitfield_info`,` $addr`:`qualified(type($addr))`,` $src`:`type($src) `)` attr-dict `->` type($result) }]; let builders = [ @@ -1764,14 +1768,15 @@ def CIR_SetBitfieldOp : CIR_Op<"set_bitfield"> { "unsigned":$size, "unsigned":$offset, "bool":$is_signed, - "bool":$is_volatile + "bool":$is_volatile, + CArg<"unsigned", "0">:$alignment ), [{ BitfieldInfoAttr info = BitfieldInfoAttr::get($_builder.getContext(), name, storage_type, size, offset, is_signed); - build($_builder, $_state, type, addr, src, info, is_volatile); + build($_builder, $_state, type, addr, src, info, alignment, is_volatile); }]> ]; } @@ -1823,20 +1828,23 @@ def CIR_GetBitfieldOp : CIR_Op<"get_bitfield"> { %2 = cir.load %0 : !cir.ptr>, !cir.ptr %3 = cir.get_member %2[1] {name = "e"} : !cir.ptr -> !cir.ptr - %4 = cir.get_bitfield(#bfi_e, %3 : !cir.ptr) -> !s32i + %4 = cir.get_bitfield align(4) (#bfi_e, %3 : !cir.ptr) -> !s32i ``` }]; let arguments = (ins Arg:$addr, BitfieldInfoAttr:$bitfield_info, + DefaultValuedOptionalAttr:$alignment, UnitAttr:$is_volatile ); let results = (outs CIR_IntType:$result); - let assemblyFormat = [{ `(`$bitfield_info `,` $addr attr-dict `:` - qualified(type($addr)) `)` `->` type($result) }]; + let assemblyFormat = [{ + (`align` `(` $alignment^ `)`)? + `(`$bitfield_info `,` $addr attr-dict `:` + qualified(type($addr)) `)` `->` type($result) }]; let builders = [ OpBuilder<(ins "mlir::Type":$type, @@ -1846,14 +1854,15 @@ def CIR_GetBitfieldOp : CIR_Op<"get_bitfield"> { "unsigned":$size, "unsigned":$offset, "bool":$is_signed, - "bool":$is_volatile + "bool":$is_volatile, + CArg<"unsigned", "0">:$alignment ), [{ BitfieldInfoAttr info = BitfieldInfoAttr::get($_builder.getContext(), name, storage_type, size, offset, is_signed); - build($_builder, $_state, type, addr, info, is_volatile); + build($_builder, $_state, type, addr, info, alignment, is_volatile); }]> ]; } @@ -2934,6 +2943,45 @@ def CIR_ByteSwapOp : CIR_BitOpBase<"byte_swap", }]; } +//===----------------------------------------------------------------------===// +// RotateOp +//===----------------------------------------------------------------------===// + +def CIR_RotateOp : CIR_Op<"rotate", [Pure, SameOperandsAndResultType]> { + let summary = "Rotate the bits in the operand integer"; + let description = [{ + The `cir.rotate` rotates the bits in `input` by the given amount `amount`. + The rotate direction is specified by the `left` and `right` keyword. + + `input` must be an unsigned integer and its width must be either 8, 16, 32, + or 64. The types of `input`, `amount`, and the result must all match. + + Example: + + ```mlir + %r = cir.rotate left %0, %1 : !u32i + %r = cir.rotate right %0, %1 : !u32i + ``` + }]; + + let results = (outs CIR_IntType:$result); + let arguments = (ins + CIR_UIntOfWidths<[8, 16, 32, 64]>:$input, + CIR_IntType:$amount, + UnitAttr:$rotateLeft + ); + + let assemblyFormat = [{ + (`left` $rotateLeft^) : (`right`)? + $input `,` $amount `:` type($result) attr-dict + }]; + + let extraClassDeclaration = [{ + bool isRotateLeft() { return getRotateLeft(); } + bool isRotateRight() { return !getRotateLeft(); } + }]; +} + //===----------------------------------------------------------------------===// // Assume Operations //===----------------------------------------------------------------------===// @@ -2956,6 +3004,27 @@ def CIR_AssumeOp : CIR_Op<"assume"> { }]; } +def CIR_AssumeSepStorageOp : CIR_Op<"assume_separate_storage", [ + SameTypeOperands +]> { + let summary = + "Tell the optimizer that two pointers point to different allocations"; + let description = [{ + The `cir.assume_separate_storage` operation takes two pointers as arguments, + and the operation tells the optimizer that these two pointers point to + different allocations. + + This operation corresponds to the `__builtin_assume_separate_storage` + builtin function. + }]; + + let arguments = (ins CIR_VoidPtrType:$ptr1, CIR_VoidPtrType:$ptr2); + + let assemblyFormat = [{ + $ptr1 `,` $ptr2 `:` qualified(type($ptr1)) attr-dict + }]; +} + //===----------------------------------------------------------------------===// // Branch Probability Operations //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index 48e309063d38b..37e0a4c8c1b6b 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -252,8 +252,8 @@ struct MissingFeatures { static bool writebacks() { return false; } static bool appleKext() { return false; } static bool dtorCleanups() { return false; } - static bool completeDtors() { return false; } static bool vtableInitialization() { return false; } + static bool msvcBuiltins() { return false; } // Missing types static bool dataMemberType() { return false; } diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h index d9e328fe918bc..78a4c5738ae66 100644 --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -355,6 +355,9 @@ class Driver { phases::ID getFinalPhase(const llvm::opt::DerivedArgList &DAL, llvm::opt::Arg **FinalPhaseArg = nullptr) const; + llvm::Expected> + executeProgram(llvm::ArrayRef Args) const; + private: /// Certain options suppress the 'no input files' warning. LLVM_PREFERRED_TYPE(bool) @@ -367,10 +370,6 @@ class Driver { /// stored in it, and will clean them up when torn down. mutable llvm::StringMap> ToolChains; - /// The associated offloading architectures with each toolchain. - llvm::DenseMap> - OffloadArchs; - private: /// TranslateInputArgs - Create a new derived argument list from the input /// arguments, after applying the standard argument translations. @@ -537,8 +536,7 @@ class Driver { /// empty string. llvm::SmallVector getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args, - Action::OffloadKind Kind, const ToolChain *TC, - bool SpecificToolchain = true) const; + Action::OffloadKind Kind, const ToolChain &TC) const; /// Check that the file referenced by Value exists. If it doesn't, /// issue a diagnostic and return false. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index bce29a76f3ac7..55e90b7a0048d 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1156,7 +1156,7 @@ def offload_arch_EQ : CommaJoined<["--"], "offload-arch=">, "If 'native' is used the compiler will detect locally installed architectures. " "For HIP offloading, the device architecture can be followed by target ID features " "delimited by a colon (e.g. gfx908:xnack+:sramecc-). May be specified more than once.">; -def no_offload_arch_EQ : Joined<["--"], "no-offload-arch=">, +def no_offload_arch_EQ : CommaJoined<["--"], "no-offload-arch=">, Visibility<[ClangOption, FlangOption]>, HelpText<"Remove CUDA/HIP offloading device architecture (e.g. sm_35, gfx906) from the list of devices to compile for. " "'all' resets the list to its default value.">; @@ -1422,19 +1422,6 @@ def fno_hip_emit_relocatable : Flag<["-"], "fno-hip-emit-relocatable">, HelpText<"Do not override toolchain to compile HIP source to relocatable">; } -// Clang specific/exclusive options for OpenACC. -def openacc_macro_override - : Separate<["-"], "fexperimental-openacc-macro-override">, - Visibility<[ClangOption, CC1Option]>, - Group, - HelpText<"Overrides the _OPENACC macro value for experimental testing " - "during OpenACC support development">; -def openacc_macro_override_EQ - : Joined<["-"], "fexperimental-openacc-macro-override=">, - Alias; - -// End Clang specific/exclusive options for OpenACC. - def libomptarget_amdgpu_bc_path_EQ : Joined<["--"], "libomptarget-amdgpu-bc-path=">, Group, HelpText<"Path to libomptarget-amdgcn bitcode library">; def libomptarget_amdgcn_bc_path_EQ : Joined<["--"], "libomptarget-amdgcn-bc-path=">, Group, @@ -1637,7 +1624,7 @@ defm auto_import : BoolFOption<"auto-import", // In the future this option will be supported by other offloading // languages and accept other values such as CPU/GPU architectures, // offload kinds and target aliases. -def offload_EQ : CommaJoined<["--"], "offload=">, Flags<[NoXarchOption]>, +def offload_EQ : CommaJoined<["--"], "offload=">, Flags<[NoXarchOption]>, Alias, HelpText<"Specify comma-separated list of offloading target triples (CUDA and HIP only)">; // C++ Coroutines @@ -1917,6 +1904,14 @@ defm bounds_safety : BoolFOption< BothFlags<[], [CC1Option], " experimental bounds safety extension for C">>; +defm lifetime_safety : BoolFOption< + "experimental-lifetime-safety", + LangOpts<"EnableLifetimeSafety">, DefaultFalse, + PosFlag, + NegFlag, + BothFlags<[], [CC1Option], + " experimental lifetime safety for C++">>; + defm addrsig : BoolFOption<"addrsig", CodeGenOpts<"Addrsig">, DefaultFalse, PosFlag, @@ -2176,10 +2171,10 @@ def fwasm_exceptions : Flag<["-"], "fwasm-exceptions">, Group, HelpText<"Use WebAssembly style exceptions">; def exception_model : Separate<["-"], "exception-model">, Visibility<[CC1Option]>, HelpText<"The exception model">, - Values<"dwarf,sjlj,seh,wasm">, - NormalizedValuesScope<"LangOptions::ExceptionHandlingKind">, - NormalizedValues<["DwarfCFI", "SjLj", "WinEH", "Wasm"]>, - MarshallingInfoEnum, "None">; + Values<"dwarf,sjlj,seh,wasm,none">, + NormalizedValuesScope<"CodeGenOptions::ExceptionHandlingKind">, + NormalizedValues<["DwarfCFI", "SjLj", "WinEH", "Wasm", "None"]>, + MarshallingInfoEnum, "None">; def exception_model_EQ : Joined<["-"], "exception-model=">, Visibility<[CC1Option]>, Alias; def fignore_exceptions : Flag<["-"], "fignore-exceptions">, Group, @@ -3270,13 +3265,14 @@ defm skip_odr_check_in_gmf : BoolOption<"f", "skip-odr-check-in-gmf", "Perform ODR checks for decls in the global module fragment.">>, Group; -def modules_reduced_bmi : Flag<["-"], "fmodules-reduced-bmi">, - Group, Visibility<[ClangOption, CC1Option]>, - HelpText<"Generate the reduced BMI">, - MarshallingInfoFlag>; +defm modules_reduced_bmi : BoolOption<"f", "modules-reduced-bmi", + FrontendOpts<"GenReducedBMI">, DefaultFalse, + NegFlag, + PosFlag>; def experimental_modules_reduced_bmi : Flag<["-"], "fexperimental-modules-reduced-bmi">, - Group, Visibility<[ClangOption, CC1Option]>, Alias; + Group, Visibility<[ClangOption, CC1Option]>, Alias; def fmodules_embed_all_files : Joined<["-"], "fmodules-embed-all-files">, Visibility<[ClangOption, CC1Option, CLOption]>, @@ -7142,6 +7138,8 @@ def fintrinsic_modules_path : Separate<["-"], "fintrinsic-modules-path">, Group HelpText<"Specify where to find the compiled intrinsic modules">, DocBrief<[{This option specifies the location of pre-compiled intrinsic modules, if they are not in the default location expected by the compiler.}]>; +def fintrinsic_modules_path_EQ : Joined<["-"], "fintrinsic-modules-path=">, + Group, Alias; defm backslash : OptInFC1FFlag<"backslash", "Specify that backslash in string introduces an escape character">; defm xor_operator : OptInFC1FFlag<"xor-operator", "Enable .XOR. as a synonym of .NEQV.">; diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h index b8899e78176b4..d9f7fa2c31ade 100644 --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -202,10 +202,6 @@ class ToolChain { ToolChain(const Driver &D, const llvm::Triple &T, const llvm::opt::ArgList &Args); - /// Executes the given \p Executable and returns the stdout. - llvm::Expected> - executeToolChainProgram(StringRef Executable) const; - void setTripleEnvironment(llvm::Triple::EnvironmentType Env); virtual Tool *buildAssembler() const; diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index b4f2a87fe7e83..7677604484f52 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -4385,8 +4385,18 @@ struct FormatStyle { /// #include "B/a.h" #include "a/b.h" /// \endcode bool IgnoreCase; + /// When sorting includes in each block, only take file extensions into + /// account if two includes compare equal otherwise. + /// \code + /// true: false: + /// # include "A.h" vs. # include "A-util.h" + /// # include "A.inc" # include "A.h" + /// # include "A-util.h" # include "A.inc" + /// \endcode + bool IgnoreExtension; bool operator==(const SortIncludesOptions &R) const { - return Enabled == R.Enabled && IgnoreCase == R.IgnoreCase; + return Enabled == R.Enabled && IgnoreCase == R.IgnoreCase && + IgnoreExtension == R.IgnoreExtension; } bool operator!=(const SortIncludesOptions &R) const { return !(*this == R); diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index 78dff1165dcf5..83d2962cbf3ba 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -175,31 +175,42 @@ class Interpreter { llvm::Expected getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const; - const llvm::SmallVectorImpl &getValuePrintingInfo() const { - return ValuePrintingInfo; - } - - Expr *SynthesizeExpr(Expr *E); + std::unique_ptr GenModule(IncrementalAction *Action = nullptr); + PartialTranslationUnit &RegisterPTU(TranslationUnitDecl *TU, + std::unique_ptr M = {}, + IncrementalAction *Action = nullptr); private: size_t getEffectivePTUSize() const; void markUserCodeStart(); llvm::Expected ExtractValueFromExpr(Expr *E); - llvm::Expected CompileDtorCall(CXXRecordDecl *CXXRD); - - CodeGenerator *getCodeGen(IncrementalAction *Action = nullptr) const; - std::unique_ptr GenModule(IncrementalAction *Action = nullptr); - PartialTranslationUnit &RegisterPTU(TranslationUnitDecl *TU, - std::unique_ptr M = {}, - IncrementalAction *Action = nullptr); // A cache for the compiled destructors used to for de-allocation of managed // clang::Values. - llvm::DenseMap Dtors; + mutable llvm::DenseMap Dtors; - llvm::SmallVector ValuePrintingInfo; + std::array ValuePrintingInfo = {0}; std::unique_ptr JITBuilder; + + /// @} + /// @name Value and pretty printing support + /// @{ + + std::string ValueDataToString(const Value &V) const; + std::string ValueTypeToString(const Value &V) const; + + llvm::Expected convertExprToValue(Expr *E); + + // When we deallocate clang::Value we need to run the destructor of the type. + // This function forces emission of the needed dtor. + llvm::Expected + CompileDtorCall(CXXRecordDecl *CXXRD) const; + + /// @} + /// @name Code generation + /// @{ + CodeGenerator *getCodeGen(IncrementalAction *Action = nullptr) const; }; } // namespace clang diff --git a/clang/include/clang/Interpreter/Value.h b/clang/include/clang/Interpreter/Value.h index a93c0841915fc..b91301e6096eb 100644 --- a/clang/include/clang/Interpreter/Value.h +++ b/clang/include/clang/Interpreter/Value.h @@ -35,6 +35,7 @@ #include "llvm/Config/llvm-config.h" // for LLVM_BUILD_LLVM_DYLIB, LLVM_BUILD_SHARED_LIBS #include "llvm/Support/Compiler.h" +#include #include // NOTE: Since the REPL itself could also include this runtime, extreme caution @@ -97,6 +98,7 @@ class REPL_EXTERNAL_VISIBILITY Value { REPL_BUILTIN_TYPES #undef X void *m_Ptr; + unsigned char m_RawBits[sizeof(long double) * 8]; // widest type }; public: @@ -111,7 +113,7 @@ class REPL_EXTERNAL_VISIBILITY Value { }; Value() = default; - Value(Interpreter *In, void *Ty); + Value(const Interpreter *In, void *Ty); Value(const Value &RHS); Value(Value &&RHS) noexcept; Value &operator=(const Value &RHS); @@ -124,9 +126,7 @@ class REPL_EXTERNAL_VISIBILITY Value { void dump() const; void clear(); - ASTContext &getASTContext(); const ASTContext &getASTContext() const; - Interpreter &getInterpreter(); const Interpreter &getInterpreter() const; QualType getType() const; @@ -140,6 +140,7 @@ class REPL_EXTERNAL_VISIBILITY Value { void *getPtr() const; void setPtr(void *Ptr) { Data.m_Ptr = Ptr; } + void setRawBits(void *Ptr, unsigned NBits = sizeof(Storage)); #define X(type, name) \ void set##name(type Val) { Data.m_##name = Val; } \ @@ -193,7 +194,7 @@ class REPL_EXTERNAL_VISIBILITY Value { } }; - Interpreter *Interp = nullptr; + const Interpreter *Interp = nullptr; void *OpaqueType = nullptr; Storage Data; Kind ValueKind = K_Unspecified; @@ -205,6 +206,5 @@ template <> inline void *Value::as() const { return Data.m_Ptr; return (void *)as(); } - } // namespace clang #endif diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 4b7c8d609735f..e5680813e74de 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -44,8 +44,7 @@ namespace clang { class TypeLoc; class LangOptions; class IdentifierInfo; - class NamespaceAliasDecl; - class NamespaceDecl; + class NamespaceBaseDecl; class ObjCDeclSpec; class Sema; class Declarator; @@ -129,29 +128,15 @@ class CXXScopeSpec { /// \param Context The AST context in which this nested-name-specifier /// resides. /// - /// \param Namespace The namespace. + /// \param Namespace The namespace or the namespace alias. /// - /// \param NamespaceLoc The location of the namespace name. + /// \param NamespaceLoc The location of the namespace name or the namespace + /// alias. /// /// \param ColonColonLoc The location of the trailing '::'. - void Extend(ASTContext &Context, NamespaceDecl *Namespace, + void Extend(ASTContext &Context, NamespaceBaseDecl *Namespace, SourceLocation NamespaceLoc, SourceLocation ColonColonLoc); - /// Extend the current nested-name-specifier by another - /// nested-name-specifier component of the form 'namespace-alias::'. - /// - /// \param Context The AST context in which this nested-name-specifier - /// resides. - /// - /// \param Alias The namespace alias. - /// - /// \param AliasLoc The location of the namespace alias - /// name. - /// - /// \param ColonColonLoc The location of the trailing '::'. - void Extend(ASTContext &Context, NamespaceAliasDecl *Alias, - SourceLocation AliasLoc, SourceLocation ColonColonLoc); - /// Turn this (empty) nested-name-specifier into the global /// nested-name-specifier '::'. void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index 9135ff949eeab..d34a4146ddbd6 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -350,11 +350,6 @@ class Sema; LLVM_PREFERRED_TYPE(bool) unsigned BindsToRvalue : 1; - /// Whether this was an identity conversion with qualification - /// conversion for the implicit object argument. - LLVM_PREFERRED_TYPE(bool) - unsigned IsImplicitObjectArgumentQualificationConversion : 1; - /// Whether this binds an implicit object argument to a /// non-static member function without a ref-qualifier. LLVM_PREFERRED_TYPE(bool) @@ -453,11 +448,11 @@ class Sema; #endif return true; } + if (!C.hasSameType(getFromType(), getToType(2))) + return false; if (BindsToRvalue && IsLvalueReference) return false; - if (IsImplicitObjectArgumentQualificationConversion) - return C.hasSameUnqualifiedType(getFromType(), getToType(2)); - return C.hasSameType(getFromType(), getToType(2)); + return true; } ImplicitConversionRank getRank() const; @@ -1496,8 +1491,6 @@ class Sema; OverloadingResult BestViableFunctionImpl(Sema &S, SourceLocation Loc, OverloadCandidateSet::iterator &Best); - void PerfectViableFunction(Sema &S, SourceLocation Loc, - OverloadCandidateSet::iterator &Best); }; bool isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1, diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index b331acbe606b7..73eb730ca555b 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -834,6 +834,13 @@ enum class CCEKind { ///< message. }; +/// Enums for the diagnostics of target, target_version and target_clones. +namespace DiagAttrParams { +enum DiagType { Unsupported, Duplicate, Unknown }; +enum Specifier { None, CPU, Tune }; +enum AttrName { Target, TargetClones, TargetVersion }; +} // end namespace DiagAttrParams + void inferNoReturnAttr(Sema &S, const Decl *D); /// Sema - This implements semantic analysis and AST building for C. @@ -4922,13 +4929,6 @@ class Sema final : public SemaBase { // handled later in the process, once we know how many exist. bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str); - /// Check Target Version attrs - bool checkTargetVersionAttr(SourceLocation Loc, Decl *D, StringRef Str); - bool checkTargetClonesAttrString( - SourceLocation LiteralLoc, StringRef Str, const StringLiteral *Literal, - Decl *D, bool &HasDefault, bool &HasCommas, bool &HasNotDefault, - SmallVectorImpl> &StringsBuffer); - ErrorAttr *mergeErrorAttr(Decl *D, const AttributeCommonInfo &CI, StringRef NewUserDiagnostic); FormatAttr *mergeFormatAttr(Decl *D, const AttributeCommonInfo &CI, diff --git a/clang/include/clang/Sema/SemaARM.h b/clang/include/clang/Sema/SemaARM.h index 788a7abf5f9c1..e77d65f9362d8 100644 --- a/clang/include/clang/Sema/SemaARM.h +++ b/clang/include/clang/Sema/SemaARM.h @@ -91,6 +91,11 @@ class SemaARM : public SemaBase { /// Return true if the given vector types are lax-compatible SVE vector types, /// false otherwise. bool areLaxCompatibleSveTypes(QualType FirstType, QualType SecondType); + + bool checkTargetVersionAttr(const StringRef Str, const SourceLocation Loc); + bool checkTargetClonesAttr(SmallVectorImpl &Params, + SmallVectorImpl &Locs, + SmallVectorImpl> &NewParams); }; SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD); diff --git a/clang/include/clang/Sema/SemaRISCV.h b/clang/include/clang/Sema/SemaRISCV.h index 8d2e1c6b7512f..844cc3ce4a440 100644 --- a/clang/include/clang/Sema/SemaRISCV.h +++ b/clang/include/clang/Sema/SemaRISCV.h @@ -55,6 +55,11 @@ class SemaRISCV : public SemaBase { bool DeclareAndesVectorBuiltins = false; std::unique_ptr IntrinsicManager; + + bool checkTargetVersionAttr(const StringRef Param, const SourceLocation Loc); + bool checkTargetClonesAttr(SmallVectorImpl &Params, + SmallVectorImpl &Locs, + SmallVectorImpl> &NewParams); }; std::unique_ptr diff --git a/clang/include/clang/Sema/SemaX86.h b/clang/include/clang/Sema/SemaX86.h index b5a23f1bede04..20783e344c02f 100644 --- a/clang/include/clang/Sema/SemaX86.h +++ b/clang/include/clang/Sema/SemaX86.h @@ -37,6 +37,10 @@ class SemaX86 : public SemaBase { void handleAnyInterruptAttr(Decl *D, const ParsedAttr &AL); void handleForceAlignArgPointerAttr(Decl *D, const ParsedAttr &AL); + + bool checkTargetClonesAttr(SmallVectorImpl &Params, + SmallVectorImpl &Locs, + SmallVectorImpl> &NewParams); }; } // namespace clang diff --git a/clang/include/clang/Serialization/TypeBitCodes.def b/clang/include/clang/Serialization/TypeBitCodes.def index b8cde2e370960..613eb6af2005a 100644 --- a/clang/include/clang/Serialization/TypeBitCodes.def +++ b/clang/include/clang/Serialization/TypeBitCodes.def @@ -69,5 +69,6 @@ TYPE_BIT_CODE(CountAttributed, COUNT_ATTRIBUTED, 57) TYPE_BIT_CODE(ArrayParameter, ARRAY_PARAMETER, 58) TYPE_BIT_CODE(HLSLAttributedResource, HLSLRESOURCE_ATTRIBUTED, 59) TYPE_BIT_CODE(HLSLInlineSpirv, HLSL_INLINE_SPIRV, 60) +TYPE_BIT_CODE(PredefinedSugar, PREDEFINED_SUGAR, 61) #undef TYPE_BIT_CODE diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 6370586e218ef..fbb34340a5c67 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -499,9 +499,6 @@ class ExprEngine { void VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R, ExplodedNode *Pred, ExplodedNodeSet &Dst); - void VisitInitListExpr(const InitListExpr *E, ExplodedNode *Pred, - ExplodedNodeSet &Dst); - /// VisitAttributedStmt - Transfer function logic for AttributedStmt. void VisitAttributedStmt(const AttributedStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst); @@ -591,6 +588,10 @@ class ExprEngine { ExplodedNode *Pred, ExplodedNodeSet &Dst); + void ConstructInitList(const Expr *Source, ArrayRef Args, + bool IsTransparent, ExplodedNode *Pred, + ExplodedNodeSet &Dst); + /// evalEagerlyAssumeBifurcation - Given the nodes in 'Src', eagerly assume /// concrete boolean values for 'Ex', storing the resulting nodes in 'Dst'. void evalEagerlyAssumeBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, diff --git a/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h b/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h index 43dbfb1585151..da3efd76c6aae 100644 --- a/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h +++ b/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h @@ -38,29 +38,29 @@ // function clang_registerCheckers. For example: // // extern "C" -// void clang_registerCheckers (CheckerRegistry ®istry) { -// registry.addChecker("example.MainCallChecker", -// "Disallows calls to functions called main"); +// void clang_registerCheckers(CheckerRegistry &Registry) { +// Registry.addChecker( +// "example.MainCallChecker", +// "Disallows calls to functions called main"); // } // -// The first method argument is the full name of the checker, including its -// enclosing package. By convention, the registered name of a checker is the -// name of the associated class (the template argument). -// The second method argument is a short human-readable description of the -// checker. +// The first argument of this templated method is the full name of the checker +// (including its package), while the second argument is a short description +// that is printed by `-analyzer-checker-help`. // -// The clang_registerCheckers function may add any number of checkers to the -// registry. If any checkers require additional initialization, use the three- -// argument form of CheckerRegistry::addChecker. +// A plugin may register several separate checkers by calling `addChecker()` +// multiple times. If a checker requires custom registration functions (e.g. +// checker option handling) use the non-templated overload of `addChecker` that +// takes two callback functions as the first two parameters. // // To load a checker plugin, specify the full path to the dynamic library as // the argument to the -load option in the cc1 frontend. You can then enable // your custom checker using the -analyzer-checker: // -// clang -cc1 -load -analyze -// -analyzer-checker= +// clang -cc1 -load /path/to/plugin.dylib -analyze +// -analyzer-checker=example.MainCallChecker // -// For a complete working example, see examples/analyzer-plugin. +// For complete examples, see clang/lib/Analysis/plugins/SampleAnalyzer #ifndef CLANG_ANALYZER_API_VERSION_STRING // FIXME: The Clang version string is not particularly granular; @@ -108,30 +108,25 @@ class CheckerRegistry { mgr.template registerChecker(); } - template static bool returnTrue(const CheckerManager &mgr) { - return true; - } + static bool returnTrue(const CheckerManager &) { return true; } public: - /// Adds a checker to the registry. Use this non-templated overload when your - /// checker requires custom initialization. - void addChecker(RegisterCheckerFn Fn, ShouldRegisterFunction sfn, - StringRef FullName, StringRef Desc, StringRef DocsUri, - bool IsHidden); - - /// Adds a checker to the registry. Use this templated overload when your - /// checker does not require any custom initialization. - /// This function isn't really needed and probably causes more headaches than - /// the tiny convenience that it provides, but external plugins might use it, - /// and there isn't a strong incentive to remove it. + /// Adds a checker to the registry. + /// Use this for a checker defined in a plugin if it requires custom + /// registration functions (e.g. for handling checker options). + /// NOTE: As of now `DocsUri` is never queried from the checker registry. + void addChecker(RegisterCheckerFn Fn, ShouldRegisterFunction Sfn, + StringRef FullName, StringRef Desc, + StringRef DocsUri = "NoDocsUri", bool IsHidden = false); + + /// Adds a checker to the registry. + /// Use this for a checker defined in a plugin if it doesn't require custom + /// registration functions. template - void addChecker(StringRef FullName, StringRef Desc, StringRef DocsUri, - bool IsHidden = false) { - // Avoid MSVC's Compiler Error C2276: - // http://msdn.microsoft.com/en-us/library/850cstw1(v=VS.80).aspx + void addChecker(StringRef FullName, StringRef Desc, + StringRef DocsUri = "NoDocsUri", bool IsHidden = false) { addChecker(&CheckerRegistry::initializeManager, - &CheckerRegistry::returnTrue, FullName, Desc, DocsUri, - IsHidden); + &CheckerRegistry::returnTrue, FullName, Desc, DocsUri, IsHidden); } /// Makes the checker with the full name \p fullName depend on the checker diff --git a/clang/include/clang/Tooling/Inclusions/IncludeStyle.h b/clang/include/clang/Tooling/Inclusions/IncludeStyle.h index fba90d8c51a66..bf060617deec7 100644 --- a/clang/include/clang/Tooling/Inclusions/IncludeStyle.h +++ b/clang/include/clang/Tooling/Inclusions/IncludeStyle.h @@ -126,8 +126,8 @@ struct IncludeStyle { /// * ``""`` means "arbitrary suffix" /// * ``"$"`` means "no suffix" /// - /// For example, if configured to ``"(_test)?$"``, then a header a.h would be seen - /// as the "main" include in both a.cc and a_test.cc. + /// For example, if configured to ``"(_test)?$"``, then a header a.h would be + /// seen as the "main" include in both a.cc and a_test.cc. /// \version 3.9 std::string IncludeIsMainRegex; diff --git a/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h b/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h index 015dbba26f688..271232e66626e 100644 --- a/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h +++ b/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h @@ -115,7 +115,8 @@ class RecursiveSymbolVisitor // The base visitor will visit NNSL prefixes, so we should only look at // the current NNS. if (NNS) { - const NamespaceDecl *ND = NNS.getNestedNameSpecifier()->getAsNamespace(); + const auto *ND = dyn_cast_if_present( + NNS.getNestedNameSpecifier()->getAsNamespace()); if (!visit(ND, NNS.getLocalBeginLoc(), NNS.getLocalEndLoc())) return false; } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 50bd93a143a28..6b6275faa215a 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2597,6 +2597,9 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { } break; + case Type::PredefinedSugar: + return getTypeInfo(cast(T)->desugar().getTypePtr()); + case Type::Pipe: Width = Target->getPointerWidth(LangAS::opencl_global); Align = Target->getPointerAlign(LangAS::opencl_global); @@ -5216,6 +5219,39 @@ QualType ASTContext::getDependentBitIntType(bool IsUnsigned, return QualType(New, 0); } +QualType +ASTContext::getPredefinedSugarType(PredefinedSugarType::Kind KD) const { + using Kind = PredefinedSugarType::Kind; + + if (auto *Target = PredefinedSugarTypes[llvm::to_underlying(KD)]; + Target != nullptr) + return QualType(Target, 0); + + auto getCanonicalType = [](const ASTContext &Ctx, Kind KDI) -> QualType { + switch (KDI) { + // size_t (C99TC3 6.5.3.4), signed size_t (C++23 5.13.2) and + // ptrdiff_t (C99TC3 6.5.6) Although these types are not built-in, they + // are part of the core language and are widely used. Using + // PredefinedSugarType makes these types as named sugar types rather than + // standard integer types, enabling better hints and diagnostics. + case Kind::SizeT: + return Ctx.getFromTargetType(Ctx.Target->getSizeType()); + case Kind::SignedSizeT: + return Ctx.getFromTargetType(Ctx.Target->getSignedSizeType()); + case Kind::PtrdiffT: + return Ctx.getFromTargetType(Ctx.Target->getPtrDiffType(LangAS::Default)); + } + llvm_unreachable("unexpected kind"); + }; + + auto *New = new (*this, alignof(PredefinedSugarType)) + PredefinedSugarType(KD, &Idents.get(PredefinedSugarType::getName(KD)), + getCanonicalType(*this, static_cast(KD))); + Types.push_back(New); + PredefinedSugarTypes[llvm::to_underlying(KD)] = New; + return QualType(New, 0); +} + #ifndef NDEBUG static bool NeedsInjectedClassNameType(const RecordDecl *D) { if (!isa(D)) return false; @@ -6796,14 +6832,31 @@ QualType ASTContext::getTagDeclType(const TagDecl *Decl) const { /// getSizeType - Return the unique type for "size_t" (C99 7.17), the result /// of the sizeof operator (C99 6.5.3.4p4). The value is target dependent and /// needs to agree with the definition in . -CanQualType ASTContext::getSizeType() const { +QualType ASTContext::getSizeType() const { + return getPredefinedSugarType(PredefinedSugarType::Kind::SizeT); +} + +CanQualType ASTContext::getCanonicalSizeType() const { return getFromTargetType(Target->getSizeType()); } /// Return the unique signed counterpart of the integer type /// corresponding to size_t. -CanQualType ASTContext::getSignedSizeType() const { - return getFromTargetType(Target->getSignedSizeType()); +QualType ASTContext::getSignedSizeType() const { + return getPredefinedSugarType(PredefinedSugarType::Kind::SignedSizeT); +} + +/// getPointerDiffType - Return the unique type for "ptrdiff_t" (C99 7.17) +/// defined in . Pointer - pointer requires this (C99 6.5.6p9). +QualType ASTContext::getPointerDiffType() const { + return getPredefinedSugarType(PredefinedSugarType::Kind::PtrdiffT); +} + +/// Return the unique unsigned counterpart of "ptrdiff_t" +/// integer type. The standard (C11 7.21.6.1p7) refers to this type +/// in the definition of %tu format specifier. +QualType ASTContext::getUnsignedPointerDiffType() const { + return getFromTargetType(Target->getUnsignedPtrDiffType(LangAS::Default)); } /// getIntMaxType - Return the unique type for "intmax_t" (C99 7.18.1.5). @@ -6838,19 +6891,6 @@ QualType ASTContext::getUIntPtrType() const { return getCorrespondingUnsignedType(getIntPtrType()); } -/// getPointerDiffType - Return the unique type for "ptrdiff_t" (C99 7.17) -/// defined in . Pointer - pointer requires this (C99 6.5.6p9). -QualType ASTContext::getPointerDiffType() const { - return getFromTargetType(Target->getPtrDiffType(LangAS::Default)); -} - -/// Return the unique unsigned counterpart of "ptrdiff_t" -/// integer type. The standard (C11 7.21.6.1p7) refers to this type -/// in the definition of %tu format specifier. -QualType ASTContext::getUnsignedPointerDiffType() const { - return getFromTargetType(Target->getUnsignedPtrDiffType(LangAS::Default)); -} - /// Return the unique type for "pid_t" defined in /// . We need this to compute the correct type for vfork(). QualType ASTContext::getProcessIDType() const { @@ -7387,21 +7427,9 @@ bool ASTContext::isSameDefaultTemplateArgument(const NamedDecl *X, return hasSameTemplateName(TAX.getAsTemplate(), TAY.getAsTemplate()); } -static NamespaceDecl *getNamespace(const NestedNameSpecifier *X) { - if (auto *NS = X->getAsNamespace()) - return NS; - if (auto *NAS = X->getAsNamespaceAlias()) - return NAS->getNamespace(); - return nullptr; -} - static bool isSameQualifier(const NestedNameSpecifier *X, const NestedNameSpecifier *Y) { - if (auto *NSX = getNamespace(X)) { - auto *NSY = getNamespace(Y); - if (!NSY || NSX->getCanonicalDecl() != NSY->getCanonicalDecl()) - return false; - } else if (X->getKind() != Y->getKind()) + if (X->getKind() != Y->getKind()) return false; // FIXME: For namespaces and types, we're permitted to check that the entity @@ -7412,8 +7440,8 @@ static bool isSameQualifier(const NestedNameSpecifier *X, return false; break; case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: - // We've already checked that we named the same namespace. + if (!declaresSameEntity(X->getAsNamespace(), Y->getAsNamespace())) + return false; break; case NestedNameSpecifier::TypeSpec: if (X->getAsType()->getCanonicalTypeInternal() != @@ -7836,17 +7864,10 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { NNS->getAsIdentifier()); case NestedNameSpecifier::Namespace: - // A namespace is canonical; build a nested-name-specifier with - // this namespace and no prefix. - return NestedNameSpecifier::Create(*this, nullptr, - NNS->getAsNamespace()->getFirstDecl()); - - case NestedNameSpecifier::NamespaceAlias: // A namespace is canonical; build a nested-name-specifier with // this namespace and no prefix. return NestedNameSpecifier::Create( - *this, nullptr, - NNS->getAsNamespaceAlias()->getNamespace()->getFirstDecl()); + *this, nullptr, NNS->getAsNamespace()->getNamespace()->getFirstDecl()); // The difference between TypeSpec and TypeSpecWithTemplate is that the // latter will have the 'template' keyword when printed. @@ -13698,26 +13719,27 @@ static NestedNameSpecifier *getCommonNNS(ASTContext &Ctx, R = NestedNameSpecifier::Create(Ctx, P, II); break; } - case NestedNameSpecifier::SpecifierKind::Namespace: - case NestedNameSpecifier::SpecifierKind::NamespaceAlias: { - assert(K2 == NestedNameSpecifier::SpecifierKind::Namespace || - K2 == NestedNameSpecifier::SpecifierKind::NamespaceAlias); + case NestedNameSpecifier::SpecifierKind::Namespace: { + assert(K2 == NestedNameSpecifier::SpecifierKind::Namespace); // The prefixes for namespaces are not significant, its declaration // identifies it uniquely. NestedNameSpecifier *P = ::getCommonNNS(Ctx, NNS1->getPrefix(), NNS2->getPrefix(), /*IsSame=*/false); - NamespaceAliasDecl *A1 = NNS1->getAsNamespaceAlias(), - *A2 = NNS2->getAsNamespaceAlias(); - // Are they the same namespace alias? - if (declaresSameEntity(A1, A2)) { - R = NestedNameSpecifier::Create(Ctx, P, ::getCommonDeclChecked(A1, A2)); + NamespaceBaseDecl *Namespace1 = NNS1->getAsNamespace(), + *Namespace2 = NNS2->getAsNamespace(); + auto Kind = Namespace1->getKind(); + if (Kind != Namespace2->getKind() || + (Kind == Decl::NamespaceAlias && + !declaresSameEntity(Namespace1, Namespace2))) { + R = NestedNameSpecifier::Create( + Ctx, P, + ::getCommonDeclChecked(Namespace1->getNamespace(), + Namespace2->getNamespace())); break; } - // Otherwise, look at the namespaces only. - NamespaceDecl *N1 = A1 ? A1->getNamespace() : NNS1->getAsNamespace(), - *N2 = A2 ? A2->getNamespace() : NNS2->getAsNamespace(); - R = NestedNameSpecifier::Create(Ctx, P, ::getCommonDeclChecked(N1, N2)); + R = NestedNameSpecifier::Create( + Ctx, P, ::getCommonDeclChecked(Namespace1, Namespace2)); break; } case NestedNameSpecifier::SpecifierKind::TypeSpec: { @@ -14521,6 +14543,10 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X, DX->isCountInBytes(), DX->isOrNull(), CDX); } + case Type::PredefinedSugar: + assert(cast(X)->getKind() != + cast(Y)->getKind()); + return QualType(); } llvm_unreachable("Unhandled Type Class"); } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 4d3bd985739fb..b9bdabe0b8c06 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -2080,6 +2080,11 @@ ExpectedType clang::ASTNodeImporter::VisitDependentBitIntType( *ToNumBitsExprOrErr); } +ExpectedType clang::ASTNodeImporter::VisitPredefinedSugarType( + const clang::PredefinedSugarType *T) { + return Importer.getToContext().getPredefinedSugarType(T->getKind()); +} + ExpectedType clang::ASTNodeImporter::VisitDependentSizedMatrixType( const clang::DependentSizedMatrixType *T) { Error Err = Error::success(); @@ -10063,17 +10068,10 @@ ASTImporter::Import(NestedNameSpecifier *FromNNS) { case NestedNameSpecifier::Namespace: if (ExpectedDecl NSOrErr = Import(FromNNS->getAsNamespace())) { return NestedNameSpecifier::Create(ToContext, Prefix, - cast(*NSOrErr)); + cast(*NSOrErr)); } else return NSOrErr.takeError(); - case NestedNameSpecifier::NamespaceAlias: - if (ExpectedDecl NSADOrErr = Import(FromNNS->getAsNamespaceAlias())) - return NestedNameSpecifier::Create(ToContext, Prefix, - cast(*NSADOrErr)); - else - return NSADOrErr.takeError(); - case NestedNameSpecifier::Global: return NestedNameSpecifier::GlobalSpecifier(ToContext); @@ -10139,11 +10137,6 @@ ASTImporter::Import(NestedNameSpecifierLoc FromNNS) { ToLocalEndLoc); break; - case NestedNameSpecifier::NamespaceAlias: - Builder.Extend(getToContext(), Spec->getAsNamespaceAlias(), - ToLocalBeginLoc, ToLocalEndLoc); - break; - case NestedNameSpecifier::TypeSpec: { SourceLocation ToTLoc; if (Error Err = importInto(ToTLoc, NNS.getTypeLoc().getBeginLoc())) diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index 3aa6b37844103..0f2762d5c0f14 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -598,9 +598,6 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, case NestedNameSpecifier::Namespace: return IsStructurallyEquivalent(Context, NNS1->getAsNamespace(), NNS2->getAsNamespace()); - case NestedNameSpecifier::NamespaceAlias: - return IsStructurallyEquivalent(Context, NNS1->getAsNamespaceAlias(), - NNS2->getAsNamespaceAlias()); case NestedNameSpecifier::TypeSpec: return IsStructurallyEquivalent(Context, QualType(NNS1->getAsType(), 0), QualType(NNS2->getAsType(), 0)); @@ -1480,6 +1477,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; break; } + case Type::PredefinedSugar: { + const auto *TP1 = cast(T1); + const auto *TP2 = cast(T2); + if (TP1->getKind() != TP2->getKind()) + return false; + break; + } } // end switch return true; diff --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp index 965e235036031..3288585683c10 100644 --- a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp +++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp @@ -62,7 +62,7 @@ void ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl, (Func->hasThisPointer() && !Func->isThisPointerExplicit()); for (auto ParamOffset : llvm::drop_begin(Func->ParamOffsets, Drop)) { const ParmVarDecl *PD = FuncDecl->parameters()[ParamIndex]; - std::optional T = Ctx.classify(PD->getType()); + OptPrimType T = Ctx.classify(PD->getType()); this->Params.insert({PD, {ParamOffset, T != std::nullopt}}); ++ParamIndex; } diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index ea473730350b6..07efd6f852fc2 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -237,7 +237,7 @@ bool Compiler::VisitCastExpr(const CastExpr *CE) { if (SubExpr->getType().isVolatileQualified()) return this->emitInvalidCast(CastKind::Volatile, /*Fatal=*/true, CE); - std::optional SubExprT = classify(SubExpr->getType()); + OptPrimType SubExprT = classify(SubExpr->getType()); // Prepare storage for the result. if (!Initializing && !SubExprT) { std::optional LocalIndex = allocateLocal(SubExpr); @@ -388,7 +388,7 @@ bool Compiler::VisitCastExpr(const CastExpr *CE) { const Descriptor *Desc = nullptr; const QualType PointeeType = CE->getType()->getPointeeType(); if (!PointeeType.isNull()) { - if (std::optional T = classify(PointeeType)) + if (OptPrimType T = classify(PointeeType)) Desc = P.createDescriptor(SubExpr, *T); else Desc = P.createDescriptor(SubExpr, PointeeType.getTypePtr(), @@ -436,7 +436,7 @@ bool Compiler::VisitCastExpr(const CastExpr *CE) { PrimType T = classifyPrim(IntType); QualType PtrType = CE->getType(); const Descriptor *Desc; - if (std::optional T = classify(PtrType->getPointeeType())) + if (OptPrimType T = classify(PtrType->getPointeeType())) Desc = P.createDescriptor(SubExpr, *T); else if (PtrType->getPointeeType()->isVoidType()) Desc = nullptr; @@ -473,12 +473,12 @@ bool Compiler::VisitCastExpr(const CastExpr *CE) { return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, CE); } QualType SubExprTy = SubExpr->getType(); - std::optional FromT = classify(SubExprTy); + OptPrimType FromT = classify(SubExprTy); // Casts from integer/vector to vector. if (CE->getType()->isVectorType()) return this->emitBuiltinBitCast(CE); - std::optional ToT = classify(CE->getType()); + OptPrimType ToT = classify(CE->getType()); if (!FromT || !ToT) return false; @@ -504,7 +504,7 @@ bool Compiler::VisitCastExpr(const CastExpr *CE) { case CK_IntegralToBoolean: case CK_FixedPointToBoolean: { // HLSL uses this to cast to one-element vectors. - std::optional FromT = classify(SubExpr->getType()); + OptPrimType FromT = classify(SubExpr->getType()); if (!FromT) return false; @@ -517,8 +517,8 @@ bool Compiler::VisitCastExpr(const CastExpr *CE) { case CK_BooleanToSignedIntegral: case CK_IntegralCast: { - std::optional FromT = classify(SubExpr->getType()); - std::optional ToT = classify(CE->getType()); + OptPrimType FromT = classify(SubExpr->getType()); + OptPrimType ToT = classify(CE->getType()); if (!FromT || !ToT) return false; @@ -688,7 +688,7 @@ bool Compiler::VisitCastExpr(const CastExpr *CE) { case CK_HLSLVectorTruncation: { assert(SubExpr->getType()->isVectorType()); - if (std::optional ResultT = classify(CE)) { + if (OptPrimType ResultT = classify(CE)) { assert(!DiscardResult); // Result must be either a float or integer. Take the first element. if (!this->visit(SubExpr)) @@ -872,9 +872,9 @@ bool Compiler::VisitBinaryOperator(const BinaryOperator *BO) { } // Typecheck the args. - std::optional LT = classify(LHS); - std::optional RT = classify(RHS); - std::optional T = classify(BO->getType()); + OptPrimType LT = classify(LHS); + OptPrimType RT = classify(RHS); + OptPrimType T = classify(BO->getType()); // Special case for C++'s three-way/spaceship operator <=>, which // returns a std::{strong,weak,partial}_ordering (which is a class, so doesn't @@ -995,8 +995,8 @@ bool Compiler::VisitPointerArithBinOp(const BinaryOperator *E) { (!LHS->getType()->isPointerType() && !RHS->getType()->isPointerType())) return false; - std::optional LT = classify(LHS); - std::optional RT = classify(RHS); + OptPrimType LT = classify(LHS); + OptPrimType RT = classify(RHS); if (!LT || !RT) return false; @@ -1068,7 +1068,7 @@ bool Compiler::VisitLogicalBinOp(const BinaryOperator *E) { BinaryOperatorKind Op = E->getOpcode(); const Expr *LHS = E->getLHS(); const Expr *RHS = E->getRHS(); - std::optional T = classify(E->getType()); + OptPrimType T = classify(E->getType()); if (Op == BO_LOr) { // Logical OR. Visit LHS and only evaluate RHS if LHS was FALSE. @@ -1648,7 +1648,7 @@ bool Compiler::VisitImplicitValueInitExpr( const ImplicitValueInitExpr *E) { QualType QT = E->getType(); - if (std::optional T = classify(QT)) + if (OptPrimType T = classify(QT)) return this->visitZeroInitializer(*T, QT, E); if (QT->isRecordType()) { @@ -1734,7 +1734,7 @@ bool Compiler::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { if (!Success) return false; - std::optional IndexT = classify(Index->getType()); + OptPrimType IndexT = classify(Index->getType()); // In error-recovery cases, the index expression has a dependent type. if (!IndexT) return this->emitError(E); @@ -1776,7 +1776,7 @@ bool Compiler::visitInitList(ArrayRef Inits, } // Primitive values. - if (std::optional T = classify(QT)) { + if (OptPrimType T = classify(QT)) { assert(!DiscardResult); if (Inits.size() == 0) return this->visitZeroInitializer(*T, QT, E); @@ -1840,7 +1840,7 @@ bool Compiler::visitInitList(ArrayRef Inits, FToInit = cast(E)->getInitializedFieldInUnion(); const Record::Field *FieldToInit = R->getField(FToInit); - if (std::optional T = classify(Init)) { + if (OptPrimType T = classify(Init)) { if (!initPrimitiveField(FieldToInit, Init, *T, /*Activate=*/true)) return false; } else { @@ -1859,7 +1859,7 @@ bool Compiler::visitInitList(ArrayRef Inits, R->getField(InitIndex)->isUnnamedBitField()) ++InitIndex; - if (std::optional T = classify(Init)) { + if (OptPrimType T = classify(Init)) { const Record::Field *FieldToInit = R->getField(InitIndex); if (!initPrimitiveField(FieldToInit, Init, *T)) return false; @@ -1899,7 +1899,7 @@ bool Compiler::visitInitList(ArrayRef Inits, if (!this->emitCheckArraySize(NumElems, E)) return false; - std::optional InitT = classify(CAT->getElementType()); + OptPrimType InitT = classify(CAT->getElementType()); unsigned ElementIndex = 0; for (const Expr *Init : Inits) { if (const auto *EmbedS = @@ -2013,7 +2013,7 @@ bool Compiler::visitInitList(ArrayRef Inits, /// this. template bool Compiler::visitArrayElemInit(unsigned ElemIndex, const Expr *Init, - std::optional InitT) { + OptPrimType InitT) { if (InitT) { // Visit the primitive element like normal. if (!this->visit(Init)) @@ -2042,7 +2042,7 @@ bool Compiler::visitCallArgs(ArrayRef Args, unsigned ArgIndex = 0; for (const Expr *Arg : Args) { - if (std::optional T = classify(Arg)) { + if (OptPrimType T = classify(Arg)) { if (!this->visit(Arg)) return false; } else { @@ -2097,7 +2097,7 @@ bool Compiler::VisitSubstNonTypeTemplateParmExpr( template bool Compiler::VisitConstantExpr(const ConstantExpr *E) { - std::optional T = classify(E->getType()); + OptPrimType T = classify(E->getType()); if (T && E->hasAPValueResult()) { // Try to emit the APValue directly, without visiting the subexpr. // This will only fail if we can't emit the APValue, so won't emit any @@ -2292,7 +2292,7 @@ bool Compiler::VisitMemberExpr(const MemberExpr *E) { const auto maybeLoadValue = [&]() -> bool { if (E->isGLValue()) return true; - if (std::optional T = classify(E)) + if (OptPrimType T = classify(E)) return this->emitLoadPop(*T, E); return false; }; @@ -2357,7 +2357,7 @@ bool Compiler::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) { // Investigate compiling this to a loop. const Expr *SubExpr = E->getSubExpr(); size_t Size = E->getArraySize().getZExtValue(); - std::optional SubExprT = classify(SubExpr); + OptPrimType SubExprT = classify(SubExpr); // So, every iteration, we execute an assignment here // where the LHS is on the stack (the target array) @@ -2589,8 +2589,8 @@ bool Compiler::VisitFloatCompoundAssignOperator( QualType LHSType = LHS->getType(); QualType LHSComputationType = E->getComputationLHSType(); QualType ResultType = E->getComputationResultType(); - std::optional LT = classify(LHSComputationType); - std::optional RT = classify(ResultType); + OptPrimType LT = classify(LHSComputationType); + OptPrimType RT = classify(ResultType); assert(ResultType->isFloatingType()); @@ -2659,8 +2659,8 @@ bool Compiler::VisitPointerCompoundAssignOperator( BinaryOperatorKind Op = E->getOpcode(); const Expr *LHS = E->getLHS(); const Expr *RHS = E->getRHS(); - std::optional LT = classify(LHS->getType()); - std::optional RT = classify(RHS->getType()); + OptPrimType LT = classify(LHS->getType()); + OptPrimType RT = classify(RHS->getType()); if (Op != BO_AddAssign && Op != BO_SubAssign) return false; @@ -2698,11 +2698,10 @@ bool Compiler::VisitCompoundAssignOperator( const Expr *LHS = E->getLHS(); const Expr *RHS = E->getRHS(); - std::optional LHSComputationT = - classify(E->getComputationLHSType()); - std::optional LT = classify(LHS->getType()); - std::optional RT = classify(RHS->getType()); - std::optional ResultT = classify(E->getType()); + OptPrimType LHSComputationT = classify(E->getComputationLHSType()); + OptPrimType LT = classify(LHS->getType()); + OptPrimType RT = classify(RHS->getType()); + OptPrimType ResultT = classify(E->getType()); if (!Ctx.getLangOpts().CPlusPlus14) return this->visit(RHS) && this->visit(LHS) && this->emitError(E); @@ -2837,7 +2836,7 @@ bool Compiler::VisitMaterializeTemporaryExpr( // When we're initializing a global variable *or* the storage duration of // the temporary is explicitly static, create a global variable. - std::optional SubExprT = classify(SubExpr); + OptPrimType SubExprT = classify(SubExpr); bool IsStatic = E->getStorageDuration() == SD_Static; if (IsStatic) { std::optional GlobalIndex = P.createGlobal(E); @@ -2931,7 +2930,7 @@ bool Compiler::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { return this->visitInitializer(Init) && this->emitFinishInit(E); } - std::optional T = classify(E->getType()); + OptPrimType T = classify(E->getType()); if (E->isFileScope()) { // Avoid creating a variable if this is a primitive RValue anyway. if (T && !E->isLValue()) @@ -3014,7 +3013,7 @@ bool Compiler::VisitLambdaExpr(const LambdaExpr *E) { continue; ++CaptureInitIt; - if (std::optional T = classify(Init)) { + if (OptPrimType T = classify(Init)) { if (!this->visit(Init)) return false; @@ -3061,21 +3060,21 @@ bool Compiler::VisitCXXReinterpretCastExpr( const CXXReinterpretCastExpr *E) { const Expr *SubExpr = E->getSubExpr(); - std::optional FromT = classify(SubExpr); - std::optional ToT = classify(E); + OptPrimType FromT = classify(SubExpr); + OptPrimType ToT = classify(E); if (!FromT || !ToT) return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, E); if (FromT == PT_Ptr || ToT == PT_Ptr) { // Both types could be PT_Ptr because their expressions are glvalues. - std::optional PointeeFromT; + OptPrimType PointeeFromT; if (SubExpr->getType()->isPointerOrReferenceType()) PointeeFromT = classify(SubExpr->getType()->getPointeeType()); else PointeeFromT = classify(SubExpr->getType()); - std::optional PointeeToT; + OptPrimType PointeeToT; if (E->getType()->isPointerOrReferenceType()) PointeeToT = classify(E->getType()->getPointeeType()); else @@ -3344,7 +3343,7 @@ bool Compiler::VisitCXXScalarValueInitExpr( if (DiscardResult || Ty->isVoidType()) return true; - if (std::optional T = classify(Ty)) + if (OptPrimType T = classify(Ty)) return this->visitZeroInitializer(*T, Ty, E); if (const auto *CT = Ty->getAs()) { @@ -3457,7 +3456,7 @@ bool Compiler::VisitCXXNewExpr(const CXXNewExpr *E) { assert(classifyPrim(E->getType()) == PT_Ptr); const Expr *Init = E->getInitializer(); QualType ElementType = E->getAllocatedType(); - std::optional ElemT = classify(ElementType); + OptPrimType ElemT = classify(ElementType); unsigned PlacementArgs = E->getNumPlacementArgs(); const FunctionDecl *OperatorNew = E->getOperatorNew(); const Expr *PlacementDest = nullptr; @@ -3645,7 +3644,7 @@ bool Compiler::VisitCXXNewExpr(const CXXNewExpr *E) { if (!this->emitStorePop(InitT, E)) return false; } else if (DynamicInit) { - if (std::optional InitT = classify(DynamicInit)) { + if (OptPrimType InitT = classify(DynamicInit)) { if (!this->visit(DynamicInit)) return false; if (!this->emitStorePop(*InitT, E)) @@ -4154,7 +4153,7 @@ bool Compiler::visitInitializer(const Expr *E) { } template bool Compiler::visitBool(const Expr *E) { - std::optional T = classify(E->getType()); + OptPrimType T = classify(E->getType()); if (!T) { // Convert complex values to bool. if (E->getType()->isAnyComplexType()) { @@ -4309,7 +4308,7 @@ bool Compiler::visitZeroArrayInitializer(QualType T, const Expr *E) { QualType ElemType = AT->getElementType(); size_t NumElems = cast(AT)->getZExtSize(); - if (std::optional ElemT = classify(ElemType)) { + if (OptPrimType ElemT = classify(ElemType)) { for (size_t I = 0; I != NumElems; ++I) { if (!this->visitZeroInitializer(*ElemT, ElemType, E)) return false; @@ -4602,7 +4601,7 @@ bool Compiler::visitExpr(const Expr *E, bool DestroyToplevelScope) { } // Expressions with a primitive return type. - if (std::optional T = classify(E)) { + if (OptPrimType T = classify(E)) { if (!visit(E)) return false; @@ -4679,7 +4678,7 @@ bool Compiler::visitDeclAndReturn(const VarDecl *VD, if (!this->visitVarDecl(VD, /*Toplevel=*/true)) return false; - std::optional VarT = classify(VD->getType()); + OptPrimType VarT = classify(VD->getType()); if (Context::shouldBeGloballyIndexed(VD)) { auto GlobalIndex = P.getGlobal(VD); assert(GlobalIndex); // visitVarDecl() didn't return false. @@ -4736,7 +4735,7 @@ VarCreationState Compiler::visitVarDecl(const VarDecl *VD, return VarCreationState::NotCreated(); const Expr *Init = VD->getInit(); - std::optional VarT = classify(VD->getType()); + OptPrimType VarT = classify(VD->getType()); if (Init && Init->isValueDependent()) return false; @@ -4868,7 +4867,7 @@ bool Compiler::visitAPValueInitializer(const APValue &Val, const Record::Field *RF = R->getField(I); QualType FieldType = RF->Decl->getType(); - if (std::optional PT = classify(FieldType)) { + if (OptPrimType PT = classify(FieldType)) { if (!this->visitAPValue(F, *PT, E)) return false; if (!this->emitInitField(*PT, RF->Offset, E)) @@ -4898,7 +4897,7 @@ bool Compiler::visitAPValueInitializer(const APValue &Val, QualType ElemType = ArrType->getElementType(); for (unsigned A = 0, AN = Val.getArraySize(); A != AN; ++A) { const APValue &Elem = Val.getArrayInitializedElt(A); - if (std::optional ElemT = classify(ElemType)) { + if (OptPrimType ElemT = classify(ElemType)) { if (!this->visitAPValue(Elem, *ElemT, E)) return false; if (!this->emitInitElem(*ElemT, A, E)) @@ -4958,7 +4957,7 @@ bool Compiler::VisitBuiltinCallExpr(const CallExpr *E, } QualType ReturnType = E->getType(); - std::optional ReturnT = classify(E); + OptPrimType ReturnT = classify(E); // Non-primitive return type. Prepare storage. if (!Initializing && !ReturnT && !ReturnType->isVoidType()) { @@ -5032,7 +5031,7 @@ bool Compiler::VisitCallExpr(const CallExpr *E) { BlockScope CallScope(this, ScopeKind::Call); QualType ReturnType = E->getCallReturnType(Ctx.getASTContext()); - std::optional T = classify(ReturnType); + OptPrimType T = classify(ReturnType); bool HasRVO = !ReturnType->isVoidType() && !T; if (HasRVO) { @@ -5933,7 +5932,7 @@ bool Compiler::compileConstructor(const CXXConstructorDecl *Ctor) { if (InitExpr->getType().isNull()) return false; - if (std::optional T = this->classify(InitExpr)) { + if (OptPrimType T = this->classify(InitExpr)) { if (!this->visit(InitExpr)) return false; @@ -6189,7 +6188,7 @@ bool Compiler::VisitUnaryOperator(const UnaryOperator *E) { return this->VisitVectorUnaryOperator(E); if (SubExpr->getType()->isFixedPointType()) return this->VisitFixedPointUnaryOperator(E); - std::optional T = classify(SubExpr->getType()); + OptPrimType T = classify(SubExpr->getType()); switch (E->getOpcode()) { case UO_PostInc: { // x++ @@ -6375,6 +6374,9 @@ bool Compiler::VisitUnaryOperator(const UnaryOperator *E) { if (!this->visit(SubExpr)) return false; + if (!this->emitCheckNull(E)) + return false; + if (classifyPrim(SubExpr) == PT_Ptr) return this->emitNarrowPtr(E); return true; @@ -6412,7 +6414,7 @@ bool Compiler::VisitComplexUnaryOperator(const UnaryOperator *E) { if (DiscardResult) return this->discard(SubExpr); - std::optional ResT = classify(E); + OptPrimType ResT = classify(E); auto prepareResult = [=]() -> bool { if (!ResT && !Initializing) { std::optional LocalIndex = allocateLocal(SubExpr); @@ -6634,7 +6636,7 @@ bool Compiler::visitDeclRef(const ValueDecl *D, const Expr *E) { if (std::optional Index = P.getOrCreateGlobal(D)) { if (!this->emitGetPtrGlobal(*Index, E)) return false; - if (std::optional T = classify(E->getType())) { + if (OptPrimType T = classify(E->getType())) { if (!this->visitAPValue(TPOD->getValue(), *T, E)) return false; return this->emitInitGlobal(*T, *Index, E); @@ -6670,6 +6672,11 @@ bool Compiler::visitDeclRef(const ValueDecl *D, const Expr *E) { } // Function parameters. if (const auto *PVD = dyn_cast(D)) { + if (Ctx.getLangOpts().CPlusPlus && !Ctx.getLangOpts().CPlusPlus11 && + !D->getType()->isIntegralOrEnumerationType()) { + return this->emitInvalidDeclRef(cast(E), + /*InitializerFailed=*/false, E); + } if (auto It = this->Params.find(PVD); It != this->Params.end()) { if (IsReference || !It->second.IsPtr) return this->emitGetParam(classifyPrim(E), It->second.Offset, E); @@ -7128,7 +7135,7 @@ bool Compiler::emitBuiltinBitCast(const CastExpr *E) { const Expr *SubExpr = E->getSubExpr(); QualType FromType = SubExpr->getType(); QualType ToType = E->getType(); - std::optional ToT = classify(ToType); + OptPrimType ToT = classify(ToType); assert(!ToType->isReferenceType()); @@ -7149,7 +7156,7 @@ bool Compiler::emitBuiltinBitCast(const CastExpr *E) { if (SubExpr->isGLValue() || FromType->isVectorType()) { if (!this->visit(SubExpr)) return false; - } else if (std::optional FromT = classify(SubExpr)) { + } else if (OptPrimType FromT = classify(SubExpr)) { unsigned TempOffset = allocateLocalPrimitive(SubExpr, *FromT, /*IsConst=*/true); if (!this->visit(SubExpr)) diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h index debee6726853b..503269399c757 100644 --- a/clang/lib/AST/ByteCode/Compiler.h +++ b/clang/lib/AST/ByteCode/Compiler.h @@ -254,12 +254,8 @@ class Compiler : public ConstStmtVisitor, bool>, /// If the function does not exist yet, it is compiled. const Function *getFunction(const FunctionDecl *FD); - std::optional classify(const Expr *E) const { - return Ctx.classify(E); - } - std::optional classify(QualType Ty) const { - return Ctx.classify(Ty); - } + OptPrimType classify(const Expr *E) const { return Ctx.classify(E); } + OptPrimType classify(QualType Ty) const { return Ctx.classify(Ty); } /// Classifies a known primitive type. PrimType classifyPrim(QualType Ty) const { @@ -306,7 +302,7 @@ class Compiler : public ConstStmtVisitor, bool>, bool visitInitList(ArrayRef Inits, const Expr *ArrayFiller, const Expr *E); bool visitArrayElemInit(unsigned ElemIndex, const Expr *Init, - std::optional InitT); + OptPrimType InitT); bool visitCallArgs(ArrayRef Args, const FunctionDecl *FuncDecl, bool Activate); @@ -435,7 +431,7 @@ class Compiler : public ConstStmtVisitor, bool>, bool InitStackActive = false; /// Type of the expression returned by the function. - std::optional ReturnType; + OptPrimType ReturnType; /// Switch case mapping. CaseMap CaseLabels; diff --git a/clang/lib/AST/ByteCode/Context.cpp b/clang/lib/AST/ByteCode/Context.cpp index a629ff9569428..aaeb52e0fa449 100644 --- a/clang/lib/AST/ByteCode/Context.cpp +++ b/clang/lib/AST/ByteCode/Context.cpp @@ -52,6 +52,19 @@ bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) { return Func->isValid(); } +void Context::isPotentialConstantExprUnevaluated(State &Parent, const Expr *E, + const FunctionDecl *FD) { + assert(Stk.empty()); + ++EvalID; + size_t StackSizeBefore = Stk.size(); + Compiler C(*this, *P, Parent, Stk); + + if (!C.interpretCall(FD, E)) { + C.cleanup(); + Stk.clearTo(StackSizeBefore); + } +} + bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) { ++EvalID; bool Recursing = !Stk.empty(); @@ -222,6 +235,43 @@ bool Context::evaluateCharRange(State &Parent, const Expr *SizeExpr, return evaluateStringRepr(Parent, SizeExpr, PtrExpr, Result); } +bool Context::evaluateStrlen(State &Parent, const Expr *E, uint64_t &Result) { + assert(Stk.empty()); + Compiler C(*this, *P, Parent, Stk); + + auto PtrRes = C.interpretAsPointer(E, [&](const Pointer &Ptr) { + const Descriptor *FieldDesc = Ptr.getFieldDesc(); + if (!FieldDesc->isPrimitiveArray()) + return false; + + unsigned N = Ptr.getNumElems(); + if (Ptr.elemSize() == 1) { + Result = strnlen(reinterpret_cast(Ptr.getRawAddress()), N); + return Result != N; + } + + PrimType ElemT = FieldDesc->getPrimType(); + Result = 0; + for (unsigned I = Ptr.getIndex(); I != N; ++I) { + INT_TYPE_SWITCH(ElemT, { + auto Elem = Ptr.elem(I); + if (Elem.isZero()) + return true; + ++Result; + }); + } + // We didn't find a 0 byte. + return false; + }); + + if (PtrRes.isInvalid()) { + C.cleanup(); + Stk.clear(); + return false; + } + return true; +} + const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); } static PrimType integralTypeToPrimTypeS(unsigned BitWidth) { @@ -256,7 +306,7 @@ static PrimType integralTypeToPrimTypeU(unsigned BitWidth) { llvm_unreachable("Unhandled BitWidth"); } -std::optional Context::classify(QualType T) const { +OptPrimType Context::classify(QualType T) const { if (const auto *BT = dyn_cast(T.getCanonicalType())) { auto Kind = BT->getKind(); @@ -492,7 +542,7 @@ const Function *Context::getOrCreateFunction(const FunctionDecl *FuncDecl) { // Assign descriptors to all parameters. // Composite objects are lowered to pointers. for (const ParmVarDecl *PD : FuncDecl->parameters()) { - std::optional T = classify(PD->getType()); + OptPrimType T = classify(PD->getType()); PrimType PT = T.value_or(PT_Ptr); Descriptor *Desc = P->createDescriptor(PD, PT); ParamDescriptors.insert({ParamOffset, {PT, Desc}}); @@ -520,7 +570,7 @@ const Function *Context::getOrCreateObjCBlock(const BlockExpr *E) { // Assign descriptors to all parameters. // Composite objects are lowered to pointers. for (const ParmVarDecl *PD : BD->parameters()) { - std::optional T = classify(PD->getType()); + OptPrimType T = classify(PD->getType()); PrimType PT = T.value_or(PT_Ptr); Descriptor *Desc = P->createDescriptor(PD, PT); ParamDescriptors.insert({ParamOffset, {PT, Desc}}); diff --git a/clang/lib/AST/ByteCode/Context.h b/clang/lib/AST/ByteCode/Context.h index 5898ab5e54599..62ef5297bd19f 100644 --- a/clang/lib/AST/ByteCode/Context.h +++ b/clang/lib/AST/ByteCode/Context.h @@ -47,7 +47,9 @@ class Context final { ~Context(); /// Checks if a function is a potential constant expression. - bool isPotentialConstantExpr(State &Parent, const FunctionDecl *FnDecl); + bool isPotentialConstantExpr(State &Parent, const FunctionDecl *FD); + void isPotentialConstantExprUnevaluated(State &Parent, const Expr *E, + const FunctionDecl *FD); /// Evaluates a toplevel expression as an rvalue. bool evaluateAsRValue(State &Parent, const Expr *E, APValue &Result); @@ -64,6 +66,10 @@ class Context final { bool evaluateCharRange(State &Parent, const Expr *SizeExpr, const Expr *PtrExpr, std::string &Result); + /// Evalute \param E and if it can be evaluated to a string literal, + /// run strlen() on it. + bool evaluateStrlen(State &Parent, const Expr *E, uint64_t &Result); + /// Returns the AST context. ASTContext &getASTContext() const { return Ctx; } /// Returns the language options. @@ -76,10 +82,10 @@ class Context final { uint32_t getBitWidth(QualType T) const { return Ctx.getIntWidth(T); } /// Classifies a type. - std::optional classify(QualType T) const; + OptPrimType classify(QualType T) const; /// Classifies an expression. - std::optional classify(const Expr *E) const { + OptPrimType classify(const Expr *E) const { assert(E); if (E->isGLValue()) return PT_Ptr; diff --git a/clang/lib/AST/ByteCode/Descriptor.cpp b/clang/lib/AST/ByteCode/Descriptor.cpp index c89eca9bef440..5b9f44518fcc2 100644 --- a/clang/lib/AST/ByteCode/Descriptor.cpp +++ b/clang/lib/AST/ByteCode/Descriptor.cpp @@ -162,6 +162,8 @@ static void initField(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, Desc->IsConst = IsConst || D->IsConst; Desc->IsFieldMutable = IsMutable || D->IsMutable; Desc->IsVolatile = IsVolatile || D->IsVolatile; + // True if this field is const AND the parent is mutable. + Desc->IsConstInMutable = Desc->IsConst && IsMutable; if (auto Fn = D->CtorFn) Fn(B, Ptr + FieldOffset, Desc->IsConst, Desc->IsFieldMutable, diff --git a/clang/lib/AST/ByteCode/Descriptor.h b/clang/lib/AST/ByteCode/Descriptor.h index 4591eabb69bb4..4c925f6f0af1e 100644 --- a/clang/lib/AST/ByteCode/Descriptor.h +++ b/clang/lib/AST/ByteCode/Descriptor.h @@ -101,6 +101,10 @@ struct InlineDescriptor { /// Flag indicating if the field is mutable (if in a record). LLVM_PREFERRED_TYPE(bool) unsigned IsFieldMutable : 1; + /// Flag indicating if this field is a const field nested in + /// a mutable parent field. + LLVM_PREFERRED_TYPE(bool) + unsigned IsConstInMutable : 1; /// Flag indicating if the field is an element of a composite array. LLVM_PREFERRED_TYPE(bool) unsigned IsArrayElement : 1; @@ -160,7 +164,7 @@ struct Descriptor final { /// The primitive type this descriptor was created for, /// or the primitive element type in case this is /// a primitive array. - const std::optional PrimT = std::nullopt; + const OptPrimType PrimT = std::nullopt; /// Flag indicating if the block is mutable. const bool IsConst = false; /// Flag indicating if a field is mutable. diff --git a/clang/lib/AST/ByteCode/Disasm.cpp b/clang/lib/AST/ByteCode/Disasm.cpp index f64501f4a31e8..74399d177b5a2 100644 --- a/clang/lib/AST/ByteCode/Disasm.cpp +++ b/clang/lib/AST/ByteCode/Disasm.cpp @@ -445,6 +445,7 @@ LLVM_DUMP_METHOD void InlineDescriptor::dump(llvm::raw_ostream &OS) const { OS << "InUnion: " << InUnion << "\n"; OS << "IsFieldMutable: " << IsFieldMutable << "\n"; OS << "IsArrayElement: " << IsArrayElement << "\n"; + OS << "IsConstInMutable: " << IsConstInMutable << '\n'; OS << "Desc: "; if (Desc) Desc->dump(OS); diff --git a/clang/lib/AST/ByteCode/EvalEmitter.cpp b/clang/lib/AST/ByteCode/EvalEmitter.cpp index 5498065657e0a..81ebc5694d6f0 100644 --- a/clang/lib/AST/ByteCode/EvalEmitter.cpp +++ b/clang/lib/AST/ByteCode/EvalEmitter.cpp @@ -90,6 +90,19 @@ EvaluationResult EvalEmitter::interpretAsPointer(const Expr *E, return std::move(this->EvalResult); } +bool EvalEmitter::interpretCall(const FunctionDecl *FD, const Expr *E) { + // Add parameters to the parameter map. The values in the ParamOffset don't + // matter in this case as reading from them can't ever work. + for (const ParmVarDecl *PD : FD->parameters()) { + this->Params.insert({PD, {0, false}}); + } + + if (!this->visit(E)) + return false; + PrimType T = Ctx.classify(E).value_or(PT_Ptr); + return this->emitPop(T, E); +} + void EvalEmitter::emitLabel(LabelTy Label) { CurrentLabel = Label; } EvalEmitter::LabelTy EvalEmitter::getLabel() { return NextLabel++; } @@ -311,7 +324,7 @@ void EvalEmitter::updateGlobalTemporaries() { const Pointer &Ptr = P.getPtrGlobal(*GlobalIndex); APValue *Cached = Temp->getOrCreateValue(true); - if (std::optional T = Ctx.classify(E->getType())) { + if (OptPrimType T = Ctx.classify(E->getType())) { TYPE_SWITCH( *T, { *Cached = Ptr.deref().toAPValue(Ctx.getASTContext()); }); } else { diff --git a/clang/lib/AST/ByteCode/EvalEmitter.h b/clang/lib/AST/ByteCode/EvalEmitter.h index 7303adba22af7..2fe7da608c739 100644 --- a/clang/lib/AST/ByteCode/EvalEmitter.h +++ b/clang/lib/AST/ByteCode/EvalEmitter.h @@ -40,6 +40,9 @@ class EvalEmitter : public SourceMapper { EvaluationResult interpretDecl(const VarDecl *VD, bool CheckFullyInitialized); /// Interpret the given Expr to a Pointer. EvaluationResult interpretAsPointer(const Expr *E, PtrCallback PtrCB); + /// Interpret the given expression as if it was in the body of the given + /// function, i.e. the parameters of the function are available for use. + bool interpretCall(const FunctionDecl *FD, const Expr *E); /// Clean up all resources. void cleanup(); diff --git a/clang/lib/AST/ByteCode/EvaluationResult.cpp b/clang/lib/AST/ByteCode/EvaluationResult.cpp index f59612bf00015..b11531f4296a2 100644 --- a/clang/lib/AST/ByteCode/EvaluationResult.cpp +++ b/clang/lib/AST/ByteCode/EvaluationResult.cpp @@ -204,7 +204,7 @@ static void collectBlocks(const Pointer &Ptr, } else if (Desc->isPrimitiveArray() && Desc->getPrimType() == PT_Ptr) { for (unsigned I = 0; I != Desc->getNumElems(); ++I) { - const Pointer &ElemPointee = Ptr.atIndex(I).deref(); + const Pointer &ElemPointee = Ptr.elem(I); if (isUsefulPtr(ElemPointee) && !Blocks.contains(ElemPointee.block())) collectBlocks(ElemPointee, Blocks); } diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index 98fb8c8fcded5..5463aecf23087 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -142,8 +142,12 @@ static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC, return false; if (isa(D)) { - if (D->getType()->isReferenceType()) + if (D->getType()->isReferenceType()) { + if (S.inConstantContext() && S.getLangOpts().CPlusPlus && + !S.getLangOpts().CPlusPlus11) + diagnoseNonConstVariable(S, OpPC, D); return false; + } const SourceInfo &Loc = S.Current->getSource(OpPC); if (S.getLangOpts().CPlusPlus11) { @@ -566,7 +570,10 @@ bool CheckDowncast(InterpState &S, CodePtr OpPC, const Pointer &Ptr, bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { assert(Ptr.isLive() && "Pointer is not live"); - if (!Ptr.isConst() || Ptr.isMutable()) + if (!Ptr.isConst()) + return true; + + if (Ptr.isMutable() && !Ptr.isConstInMutable()) return true; if (!Ptr.isBlockPointer()) @@ -574,7 +581,7 @@ bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { // The This pointer is writable in constructors and destructors, // even if isConst() returns true. - if (llvm::find(S.InitializingBlocks, Ptr.block())) + if (llvm::is_contained(S.InitializingBlocks, Ptr.block())) return true; const QualType Ty = Ptr.getType(); @@ -658,6 +665,9 @@ bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, if (Ptr.isInitialized()) return true; + if (Ptr.isExtern() && S.checkingPotentialConstantExpression()) + return false; + if (const auto *VD = Ptr.getDeclDesc()->asVarDecl(); VD && (VD->isConstexpr() || VD->hasGlobalStorage())) { @@ -815,7 +825,7 @@ bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { return true; } -bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { +static bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { if (!CheckLive(S, OpPC, Ptr, AK_MemberCall)) return false; if (!Ptr.isDummy()) { @@ -937,7 +947,7 @@ bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) { return false; } -bool CheckCallDepth(InterpState &S, CodePtr OpPC) { +static bool CheckCallDepth(InterpState &S, CodePtr OpPC) { if ((S.Current->getDepth() + 1) > S.getLangOpts().ConstexprCallDepth) { S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_depth_limit_exceeded) @@ -1092,8 +1102,8 @@ bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr, return false; } -bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F, - const CallExpr *CE, unsigned ArgSize) { +static bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F, + const CallExpr *CE, unsigned ArgSize) { auto Args = ArrayRef(CE->getArgs(), CE->getNumArgs()); auto NonNullArgs = collectNonNullArgs(F->getDecl(), Args); unsigned Offset = 0; diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 6be68e4a978b5..b42c7665c3a35 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -98,26 +98,12 @@ bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr); /// Checks if a value can be stored in a block. bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr); -/// Checks if a method can be invoked on an object. -bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr); - /// Checks if a value can be initialized. bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr); -/// Checks if a method can be called. -bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F); - -/// Checks if calling the currently active function would exceed -/// the allowed call depth. -bool CheckCallDepth(InterpState &S, CodePtr OpPC); - /// Checks the 'this' pointer. bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This); -/// Checks if all the arguments annotated as 'nonnull' are in fact not null. -bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F, - const CallExpr *CE, unsigned ArgSize); - /// Checks if dynamic memory allocation is available in the current /// language mode. bool CheckDynamicMemoryAllocation(InterpState &S, CodePtr OpPC); @@ -482,10 +468,10 @@ inline bool Mulc(InterpState &S, CodePtr OpPC) { const Pointer &Result = S.Stk.peek(); if constexpr (std::is_same_v) { - APFloat A = LHS.atIndex(0).deref().getAPFloat(); - APFloat B = LHS.atIndex(1).deref().getAPFloat(); - APFloat C = RHS.atIndex(0).deref().getAPFloat(); - APFloat D = RHS.atIndex(1).deref().getAPFloat(); + APFloat A = LHS.elem(0).getAPFloat(); + APFloat B = LHS.elem(1).getAPFloat(); + APFloat C = RHS.elem(0).getAPFloat(); + APFloat D = RHS.elem(1).getAPFloat(); APFloat ResR(A.getSemantics()); APFloat ResI(A.getSemantics()); @@ -494,20 +480,20 @@ inline bool Mulc(InterpState &S, CodePtr OpPC) { // Copy into the result. Floating RA = S.allocFloat(A.getSemantics()); RA.copy(ResR); - Result.atIndex(0).deref() = RA; // Floating(ResR); + Result.elem(0) = RA; // Floating(ResR); Result.atIndex(0).initialize(); Floating RI = S.allocFloat(A.getSemantics()); RI.copy(ResI); - Result.atIndex(1).deref() = RI; // Floating(ResI); + Result.elem(1) = RI; // Floating(ResI); Result.atIndex(1).initialize(); Result.initialize(); } else { // Integer element type. - const T &LHSR = LHS.atIndex(0).deref(); - const T &LHSI = LHS.atIndex(1).deref(); - const T &RHSR = RHS.atIndex(0).deref(); - const T &RHSI = RHS.atIndex(1).deref(); + const T &LHSR = LHS.elem(0); + const T &LHSI = LHS.elem(1); + const T &RHSR = RHS.elem(0); + const T &RHSI = RHS.elem(1); unsigned Bits = LHSR.bitWidth(); // real(Result) = (real(LHS) * real(RHS)) - (imag(LHS) * imag(RHS)) @@ -517,7 +503,7 @@ inline bool Mulc(InterpState &S, CodePtr OpPC) { T B; if (T::mul(LHSI, RHSI, Bits, &B)) return false; - if (T::sub(A, B, Bits, &Result.atIndex(0).deref())) + if (T::sub(A, B, Bits, &Result.elem(0))) return false; Result.atIndex(0).initialize(); @@ -526,7 +512,7 @@ inline bool Mulc(InterpState &S, CodePtr OpPC) { return false; if (T::mul(LHSI, RHSR, Bits, &B)) return false; - if (T::add(A, B, Bits, &Result.atIndex(1).deref())) + if (T::add(A, B, Bits, &Result.elem(1))) return false; Result.atIndex(1).initialize(); Result.initialize(); @@ -542,10 +528,10 @@ inline bool Divc(InterpState &S, CodePtr OpPC) { const Pointer &Result = S.Stk.peek(); if constexpr (std::is_same_v) { - APFloat A = LHS.atIndex(0).deref().getAPFloat(); - APFloat B = LHS.atIndex(1).deref().getAPFloat(); - APFloat C = RHS.atIndex(0).deref().getAPFloat(); - APFloat D = RHS.atIndex(1).deref().getAPFloat(); + APFloat A = LHS.elem(0).getAPFloat(); + APFloat B = LHS.elem(1).getAPFloat(); + APFloat C = RHS.elem(0).getAPFloat(); + APFloat D = RHS.elem(1).getAPFloat(); APFloat ResR(A.getSemantics()); APFloat ResI(A.getSemantics()); @@ -554,21 +540,21 @@ inline bool Divc(InterpState &S, CodePtr OpPC) { // Copy into the result. Floating RA = S.allocFloat(A.getSemantics()); RA.copy(ResR); - Result.atIndex(0).deref() = RA; // Floating(ResR); + Result.elem(0) = RA; // Floating(ResR); Result.atIndex(0).initialize(); Floating RI = S.allocFloat(A.getSemantics()); RI.copy(ResI); - Result.atIndex(1).deref() = RI; // Floating(ResI); + Result.elem(1) = RI; // Floating(ResI); Result.atIndex(1).initialize(); Result.initialize(); } else { // Integer element type. - const T &LHSR = LHS.atIndex(0).deref(); - const T &LHSI = LHS.atIndex(1).deref(); - const T &RHSR = RHS.atIndex(0).deref(); - const T &RHSI = RHS.atIndex(1).deref(); + const T &LHSR = LHS.elem(0); + const T &LHSI = LHS.elem(1); + const T &RHSR = RHS.elem(0); + const T &RHSI = RHS.elem(1); unsigned Bits = LHSR.bitWidth(); const T Zero = T::from(0, Bits); @@ -595,8 +581,8 @@ inline bool Divc(InterpState &S, CodePtr OpPC) { } // real(Result) = ((real(LHS) * real(RHS)) + (imag(LHS) * imag(RHS))) / Den - T &ResultR = Result.atIndex(0).deref(); - T &ResultI = Result.atIndex(1).deref(); + T &ResultR = Result.elem(0); + T &ResultI = Result.elem(1); if (T::mul(LHSR, RHSR, Bits, &A) || T::mul(LHSI, RHSI, Bits, &B)) return false; @@ -1322,7 +1308,7 @@ bool Dup(InterpState &S, CodePtr OpPC) { template ::T> bool Pop(InterpState &S, CodePtr OpPC) { - S.Stk.pop(); + S.Stk.discard(); return true; } @@ -1899,6 +1885,16 @@ inline bool Dump(InterpState &S, CodePtr OpPC) { return true; } +inline bool CheckNull(InterpState &S, CodePtr OpPC) { + const auto &Ptr = S.Stk.peek(); + if (Ptr.isZero()) { + S.FFDiag(S.Current->getSource(OpPC), + diag::note_constexpr_dereferencing_null); + return S.noteUndefinedBehavior(); + } + return true; +} + inline bool VirtBaseHelper(InterpState &S, CodePtr OpPC, const RecordDecl *Decl, const Pointer &Ptr) { Pointer Base = Ptr; @@ -3107,7 +3103,7 @@ inline bool ArrayElem(InterpState &S, CodePtr OpPC, uint32_t Index) { return false; assert(Ptr.atIndex(Index).getFieldDesc()->getPrimType() == Name); - S.Stk.push(Ptr.atIndex(Index).deref()); + S.Stk.push(Ptr.elem(Index)); return true; } @@ -3119,7 +3115,7 @@ inline bool ArrayElemPop(InterpState &S, CodePtr OpPC, uint32_t Index) { return false; assert(Ptr.atIndex(Index).getFieldDesc()->getPrimType() == Name); - S.Stk.push(Ptr.atIndex(Index).deref()); + S.Stk.push(Ptr.elem(Index)); return true; } @@ -3561,12 +3557,22 @@ inline bool BitCastPrim(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte, Floating Result = S.allocFloat(*Sem); Floating::bitcastFromMemory(Buff.data(), *Sem, &Result); S.Stk.push(Result); - - // S.Stk.push(T::bitcastFromMemory(Buff.data(), *Sem)); } else if constexpr (needsAlloc()) { T Result = S.allocAP(ResultBitWidth); T::bitcastFromMemory(Buff.data(), ResultBitWidth, &Result); S.Stk.push(Result); + } else if constexpr (std::is_same_v) { + // Only allow to cast single-byte integers to bool if they are either 0 + // or 1. + assert(FullBitWidth.getQuantity() == 8); + auto Val = static_cast(Buff[0]); + if (Val > 1) { + S.FFDiag(S.Current->getSource(OpPC), + diag::note_constexpr_bit_cast_unrepresentable_value) + << S.getASTContext().BoolTy << Val; + return false; + } + S.Stk.push(T::bitcastFromMemory(Buff.data(), ResultBitWidth)); } else { assert(!Sem); S.Stk.push(T::bitcastFromMemory(Buff.data(), ResultBitWidth)); diff --git a/clang/lib/AST/ByteCode/InterpBlock.h b/clang/lib/AST/ByteCode/InterpBlock.h index 7798b6f886a85..51622238e275c 100644 --- a/clang/lib/AST/ByteCode/InterpBlock.h +++ b/clang/lib/AST/ByteCode/InterpBlock.h @@ -14,11 +14,6 @@ #define LLVM_CLANG_AST_INTERP_BLOCK_H #include "Descriptor.h" -#include "clang/AST/ComparisonCategories.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/Expr.h" -#include "llvm/ADT/PointerUnion.h" #include "llvm/Support/raw_ostream.h" namespace clang { diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index de0b97fd93c76..19d4c0c5b48d2 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "../ExprConstShared.h" #include "Boolean.h" -#include "Compiler.h" #include "EvalEmitter.h" #include "Interp.h" #include "InterpBuiltinBitCast.h" @@ -54,7 +53,7 @@ static APSInt popToAPSInt(InterpStack &Stk, PrimType T) { static void pushInteger(InterpState &S, const APSInt &Val, QualType QT) { assert(QT->isSignedIntegerOrEnumerationType() || QT->isUnsignedIntegerOrEnumerationType()); - std::optional T = S.getContext().classify(QT); + OptPrimType T = S.getContext().classify(QT); assert(T); unsigned BitWidth = S.getASTContext().getTypeSize(QT); @@ -1099,9 +1098,9 @@ static bool interp__builtin_complex(InterpState &S, CodePtr OpPC, const Floating &Arg1 = S.Stk.pop(); Pointer &Result = S.Stk.peek(); - Result.atIndex(0).deref() = Arg1; + Result.elem(0) = Arg1; Result.atIndex(0).initialize(); - Result.atIndex(1).deref() = Arg2; + Result.elem(1) = Arg2; Result.atIndex(1).initialize(); Result.initialize(); @@ -1531,7 +1530,7 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC, return false; bool IsArray = NumElems.ugt(1); - std::optional ElemT = S.getContext().classify(ElemType); + OptPrimType ElemT = S.getContext().classify(ElemType); DynamicAllocator &Allocator = S.getAllocator(); if (ElemT) { Block *B = @@ -1645,10 +1644,10 @@ static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC, unsigned NumElems = Arg.getNumElems(); INT_TYPE_SWITCH_NO_BOOL(ElemT, { - T Result = Arg.atIndex(0).deref(); + T Result = Arg.elem(0); unsigned BitWidth = Result.bitWidth(); for (unsigned I = 1; I != NumElems; ++I) { - T Elem = Arg.atIndex(I).deref(); + T Elem = Arg.elem(I); T PrevResult = Result; if (ID == Builtin::BI__builtin_reduce_add) { @@ -1724,11 +1723,10 @@ static bool interp__builtin_elementwise_popcount(InterpState &S, CodePtr OpPC, for (unsigned I = 0; I != NumElems; ++I) { INT_TYPE_SWITCH_NO_BOOL(ElemT, { if (BuiltinID == Builtin::BI__builtin_elementwise_popcount) { - Dst.atIndex(I).deref() = - T::from(Arg.atIndex(I).deref().toAPSInt().popcount()); + Dst.elem(I) = T::from(Arg.elem(I).toAPSInt().popcount()); } else { - Dst.atIndex(I).deref() = T::from( - Arg.atIndex(I).deref().toAPSInt().reverseBits().getZExtValue()); + Dst.elem(I) = + T::from(Arg.elem(I).toAPSInt().reverseBits().getZExtValue()); } Dst.atIndex(I).initialize(); }); @@ -2297,8 +2295,8 @@ static bool interp__builtin_elementwise_sat(InterpState &S, CodePtr OpPC, APSInt Elem1; APSInt Elem2; INT_TYPE_SWITCH_NO_BOOL(ElemT, { - Elem1 = LHS.atIndex(I).deref().toAPSInt(); - Elem2 = RHS.atIndex(I).deref().toAPSInt(); + Elem1 = LHS.elem(I).toAPSInt(); + Elem2 = RHS.elem(I).toAPSInt(); }); APSInt Result; @@ -2881,7 +2879,7 @@ static bool copyRecord(InterpState &S, CodePtr OpPC, const Pointer &Src, auto copyField = [&](const Record::Field &F, bool Activate) -> bool { Pointer DestField = Dest.atField(F.Offset); - if (std::optional FT = S.Ctx.classify(F.Decl->getType())) { + if (OptPrimType FT = S.Ctx.classify(F.Decl->getType())) { TYPE_SWITCH(*FT, { DestField.deref() = Src.atField(F.Offset).deref(); if (Src.atField(F.Offset).isInitialized()) @@ -2906,6 +2904,8 @@ static bool copyRecord(InterpState &S, CodePtr OpPC, const Pointer &Src, if (!copyField(F, /*Activate=*/true)) return false; } else { + if (!CheckMutable(S, OpPC, Src.atField(F.Offset))) + return false; Pointer DestField = Dest.atField(F.Offset); zeroAll(DestField); } @@ -2941,7 +2941,7 @@ static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src, for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) { Pointer DestElem = Dest.atIndex(I); TYPE_SWITCH(ET, { - DestElem.deref() = Src.atIndex(I).deref(); + DestElem.deref() = Src.elem(I); DestElem.initialize(); }); } diff --git a/clang/lib/AST/ByteCode/InterpFrame.cpp b/clang/lib/AST/ByteCode/InterpFrame.cpp index a5a4bd25fe712..d62a4f6275b50 100644 --- a/clang/lib/AST/ByteCode/InterpFrame.cpp +++ b/clang/lib/AST/ByteCode/InterpFrame.cpp @@ -128,6 +128,11 @@ static bool shouldSkipInBacktrace(const Function *F) { if (FD->getDeclName().getCXXOverloadedOperator() == OO_New || FD->getDeclName().getCXXOverloadedOperator() == OO_Array_New) return true; + + if (const auto *MD = dyn_cast(FD); + MD && MD->getParent()->isAnonymousStructOrUnion()) + return true; + return false; } diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td index 804853d29512e..80703ad72d954 100644 --- a/clang/lib/AST/ByteCode/Opcodes.td +++ b/clang/lib/AST/ByteCode/Opcodes.td @@ -865,6 +865,7 @@ def CheckNewTypeMismatchArray : Opcode { def IsConstantContext: Opcode; def CheckAllocations : Opcode; +def CheckNull : Opcode; def BitCastTypeClass : TypeClass { let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index 2f9ecf98e558e..4019b74669282 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -665,7 +665,7 @@ std::optional Pointer::toRValue(const Context &Ctx, return false; // Primitive values. - if (std::optional T = Ctx.classify(Ty)) { + if (OptPrimType T = Ctx.classify(Ty)) { TYPE_SWITCH(*T, R = Ptr.deref().toAPValue(ASTCtx)); return true; } @@ -682,7 +682,7 @@ std::optional Pointer::toRValue(const Context &Ctx, const Pointer &FP = Ptr.atField(F.Offset); QualType FieldTy = F.Decl->getType(); if (FP.isActive()) { - if (std::optional T = Ctx.classify(FieldTy)) { + if (OptPrimType T = Ctx.classify(FieldTy)) { TYPE_SWITCH(*T, Value = FP.deref().toAPValue(ASTCtx)); } else { Ok &= Composite(FieldTy, FP, Value); @@ -705,7 +705,7 @@ std::optional Pointer::toRValue(const Context &Ctx, const Pointer &FP = Ptr.atField(FD->Offset); APValue &Value = R.getStructField(I); - if (std::optional T = Ctx.classify(FieldTy)) { + if (OptPrimType T = Ctx.classify(FieldTy)) { TYPE_SWITCH(*T, Value = FP.deref().toAPValue(ASTCtx)); } else { Ok &= Composite(FieldTy, FP, Value); @@ -743,7 +743,7 @@ std::optional Pointer::toRValue(const Context &Ctx, for (unsigned I = 0; I < NumElems; ++I) { APValue &Slot = R.getArrayInitializedElt(I); const Pointer &EP = Ptr.atIndex(I); - if (std::optional T = Ctx.classify(ElemTy)) { + if (OptPrimType T = Ctx.classify(ElemTy)) { TYPE_SWITCH(*T, Slot = EP.deref().toAPValue(ASTCtx)); } else { Ok &= Composite(ElemTy, EP.narrow(), Slot); @@ -757,17 +757,17 @@ std::optional Pointer::toRValue(const Context &Ctx, QualType ElemTy = CT->getElementType(); if (ElemTy->isIntegerType()) { - std::optional ElemT = Ctx.classify(ElemTy); + OptPrimType ElemT = Ctx.classify(ElemTy); assert(ElemT); INT_TYPE_SWITCH(*ElemT, { - auto V1 = Ptr.atIndex(0).deref(); - auto V2 = Ptr.atIndex(1).deref(); + auto V1 = Ptr.elem(0); + auto V2 = Ptr.elem(1); R = APValue(V1.toAPSInt(), V2.toAPSInt()); return true; }); } else if (ElemTy->isFloatingType()) { - R = APValue(Ptr.atIndex(0).deref().getAPFloat(), - Ptr.atIndex(1).deref().getAPFloat()); + R = APValue(Ptr.elem(0).getAPFloat(), + Ptr.elem(1).getAPFloat()); return true; } return false; @@ -782,9 +782,8 @@ std::optional Pointer::toRValue(const Context &Ctx, SmallVector Values; Values.reserve(VT->getNumElements()); for (unsigned I = 0; I != VT->getNumElements(); ++I) { - TYPE_SWITCH(ElemT, { - Values.push_back(Ptr.atIndex(I).deref().toAPValue(ASTCtx)); - }); + TYPE_SWITCH(ElemT, + { Values.push_back(Ptr.elem(I).toAPValue(ASTCtx)); }); } assert(Values.size() == VT->getNumElements()); @@ -804,7 +803,7 @@ std::optional Pointer::toRValue(const Context &Ctx, return toAPValue(ASTCtx); // Just load primitive types. - if (std::optional T = Ctx.classify(ResultType)) { + if (OptPrimType T = Ctx.classify(ResultType)) { TYPE_SWITCH(*T, return this->deref().toAPValue(ASTCtx)); } diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h index e6a64e6658f06..d17eba5da9ca6 100644 --- a/clang/lib/AST/ByteCode/Pointer.h +++ b/clang/lib/AST/ByteCode/Pointer.h @@ -576,6 +576,11 @@ class Pointer { return true; return isRoot() ? getDeclDesc()->IsConst : getInlineDesc()->IsConst; } + bool isConstInMutable() const { + if (!isBlockPointer()) + return false; + return isRoot() ? false : getInlineDesc()->IsConstInMutable; + } /// Checks if an object or a subfield is volatile. bool isVolatile() const { @@ -688,6 +693,25 @@ class Pointer { return *reinterpret_cast(asBlockPointer().Pointee->rawData() + Offset); } + /// Dereferences the element at index \p I. + /// This is equivalent to atIndex(I).deref(). + template T &elem(unsigned I) const { + assert(isLive() && "Invalid pointer"); + assert(isBlockPointer()); + assert(asBlockPointer().Pointee); + assert(isDereferencable()); + assert(getFieldDesc()->isPrimitiveArray()); + + unsigned ElemByteOffset = I * getFieldDesc()->getElemSize(); + if (isArrayRoot()) + return *reinterpret_cast(asBlockPointer().Pointee->rawData() + + asBlockPointer().Base + sizeof(InitMapPtr) + + ElemByteOffset); + + return *reinterpret_cast(asBlockPointer().Pointee->rawData() + Offset + + ElemByteOffset); + } + /// Whether this block can be read from at all. This is only true for /// block pointers that point to a valid location inside that block. bool isDereferencable() const { diff --git a/clang/lib/AST/ByteCode/PrimType.h b/clang/lib/AST/ByteCode/PrimType.h index a156cccbb3c1b..38c29b9f82672 100644 --- a/clang/lib/AST/ByteCode/PrimType.h +++ b/clang/lib/AST/ByteCode/PrimType.h @@ -13,6 +13,7 @@ #ifndef LLVM_CLANG_AST_INTERP_TYPE_H #define LLVM_CLANG_AST_INTERP_TYPE_H +#include "clang/Basic/UnsignedOrNone.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -49,6 +50,38 @@ enum PrimType : unsigned { PT_MemberPtr = 14, }; +// Like std::optional, but only sizeof(PrimType). +class OptPrimType final { + unsigned V = ~0u; + +public: + OptPrimType() = default; + OptPrimType(std::nullopt_t) {} + OptPrimType(PrimType T) : V(static_cast(T)) {} + + explicit constexpr operator bool() const { return V != ~0u; } + PrimType operator*() const { + assert(operator bool()); + return static_cast(V); + } + + PrimType value_or(PrimType PT) const { + if (operator bool()) + return static_cast(V); + return PT; + } + + bool operator==(PrimType PT) const { + if (!operator bool()) + return false; + return V == static_cast(PT); + } + bool operator==(OptPrimType OPT) const { return V == OPT.V; } + bool operator!=(PrimType PT) const { return !(*this == PT); } + bool operator!=(OptPrimType OPT) const { return V != OPT.V; } +}; +static_assert(sizeof(OptPrimType) == sizeof(PrimType)); + inline constexpr bool isPtrType(PrimType T) { return T == PT_Ptr || T == PT_MemberPtr; } diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp index 5ac0f59f32d4e..7002724a7a4fe 100644 --- a/clang/lib/AST/ByteCode/Program.cpp +++ b/clang/lib/AST/ByteCode/Program.cpp @@ -74,27 +74,25 @@ unsigned Program::createGlobalString(const StringLiteral *S, const Expr *Base) { const Pointer Ptr(G->block()); if (CharWidth == 1) { - std::memcpy(&Ptr.atIndex(0).deref(), S->getString().data(), - StringLength); + std::memcpy(&Ptr.elem(0), S->getString().data(), StringLength); } else { // Construct the string in storage. for (unsigned I = 0; I <= StringLength; ++I) { - Pointer Field = Ptr.atIndex(I); const uint32_t CodePoint = I == StringLength ? 0 : S->getCodeUnit(I); switch (CharType) { case PT_Sint8: { using T = PrimConv::T; - Field.deref() = T::from(CodePoint, BitWidth); + Ptr.elem(I) = T::from(CodePoint, BitWidth); break; } case PT_Uint16: { using T = PrimConv::T; - Field.deref() = T::from(CodePoint, BitWidth); + Ptr.elem(I) = T::from(CodePoint, BitWidth); break; } case PT_Uint32: { using T = PrimConv::T; - Field.deref() = T::from(CodePoint, BitWidth); + Ptr.elem(I) = T::from(CodePoint, BitWidth); break; } default: @@ -171,7 +169,7 @@ unsigned Program::getOrCreateDummy(const DeclTy &D) { assert(!QT.isNull()); Descriptor *Desc; - if (std::optional T = Ctx.classify(QT)) + if (OptPrimType T = Ctx.classify(QT)) Desc = createDescriptor(D, *T, /*SourceTy=*/nullptr, std::nullopt, /*IsConst=*/QT.isConstQualified()); else @@ -250,7 +248,7 @@ std::optional Program::createGlobal(const DeclTy &D, QualType Ty, const bool IsConst = Ty.isConstQualified(); const bool IsTemporary = D.dyn_cast(); const bool IsVolatile = Ty.isVolatileQualified(); - if (std::optional T = Ctx.classify(Ty)) + if (OptPrimType T = Ctx.classify(Ty)) Desc = createDescriptor(D, *T, nullptr, Descriptor::GlobalMD, IsConst, IsTemporary, /*IsMutable=*/false, IsVolatile); else @@ -373,7 +371,7 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) { const bool IsMutable = FD->isMutable(); const bool IsVolatile = FT.isVolatileQualified(); const Descriptor *Desc; - if (std::optional T = Ctx.classify(FT)) { + if (OptPrimType T = Ctx.classify(FT)) { Desc = createDescriptor(FD, *T, nullptr, std::nullopt, IsConst, /*isTemporary=*/false, IsMutable, IsVolatile); } else { @@ -412,7 +410,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, // Array of well-known bounds. if (const auto *CAT = dyn_cast(ArrayType)) { size_t NumElems = CAT->getZExtSize(); - if (std::optional T = Ctx.classify(ElemTy)) { + if (OptPrimType T = Ctx.classify(ElemTy)) { // Arrays of primitives. unsigned ElemSize = primSize(*T); if (std::numeric_limits::max() / ElemSize <= NumElems) { @@ -439,7 +437,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, // is forbidden on pointers to such objects. if (isa(ArrayType) || isa(ArrayType)) { - if (std::optional T = Ctx.classify(ElemTy)) { + if (OptPrimType T = Ctx.classify(ElemTy)) { return allocateDescriptor(D, *T, MDSize, IsConst, IsTemporary, Descriptor::UnknownSize{}); } else { @@ -462,7 +460,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, // Complex types - represented as arrays of elements. if (const auto *CT = Ty->getAs()) { - std::optional ElemTy = Ctx.classify(CT->getElementType()); + OptPrimType ElemTy = Ctx.classify(CT->getElementType()); if (!ElemTy) return nullptr; @@ -472,7 +470,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, // Same with vector types. if (const auto *VT = Ty->getAs()) { - std::optional ElemTy = Ctx.classify(VT->getElementType()); + OptPrimType ElemTy = Ctx.classify(VT->getElementType()); if (!ElemTy) return nullptr; diff --git a/clang/lib/AST/ByteCode/State.h b/clang/lib/AST/ByteCode/State.h index 9a81fa6b7d220..6fc33222ac956 100644 --- a/clang/lib/AST/ByteCode/State.h +++ b/clang/lib/AST/ByteCode/State.h @@ -35,6 +35,7 @@ enum AccessKinds { AK_Construct, AK_Destroy, AK_IsWithinLifetime, + AK_Dereference }; /// The order of this enum is important for diagnostics. diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 4514965009793..673e3f73858c7 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -3211,6 +3211,12 @@ UsingDirectiveDecl *UsingDirectiveDecl::CreateDeserialized(ASTContext &C, SourceLocation(), nullptr, nullptr); } +NamespaceDecl *NamespaceBaseDecl::getNamespace() { + if (auto *Alias = dyn_cast(this)) + return Alias->getNamespace(); + return cast(this); +} + NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() { if (auto *NA = dyn_cast_or_null(NominatedNamespace)) return NA->getNamespace(); @@ -3221,7 +3227,7 @@ NamespaceDecl::NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, NamespaceDecl *PrevDecl, bool Nested) - : NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace), + : NamespaceBaseDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace), redeclarable_base(C), LocStart(StartLoc) { setInline(Inline); setNested(Nested); @@ -3268,13 +3274,11 @@ NamespaceAliasDecl *NamespaceAliasDecl::getMostRecentDeclImpl() { return getMostRecentDecl(); } -NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation UsingLoc, - SourceLocation AliasLoc, - IdentifierInfo *Alias, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation IdentLoc, - NamedDecl *Namespace) { +NamespaceAliasDecl *NamespaceAliasDecl::Create( + ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, + SourceLocation AliasLoc, IdentifierInfo *Alias, + NestedNameSpecifierLoc QualifierLoc, SourceLocation IdentLoc, + NamespaceBaseDecl *Namespace) { // FIXME: Preserve the aliased namespace as written. if (auto *NS = dyn_cast_or_null(Namespace)) Namespace = NS->getFirstDecl(); diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 1b33b6706e204..0d12161756467 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -1529,7 +1529,7 @@ CallStackFrame::~CallStackFrame() { static bool isRead(AccessKinds AK) { return AK == AK_Read || AK == AK_ReadObjectRepresentation || - AK == AK_IsWithinLifetime; + AK == AK_IsWithinLifetime || AK == AK_Dereference; } static bool isModification(AccessKinds AK) { @@ -1540,6 +1540,7 @@ static bool isModification(AccessKinds AK) { case AK_DynamicCast: case AK_TypeId: case AK_IsWithinLifetime: + case AK_Dereference: return false; case AK_Assign: case AK_Increment: @@ -1558,15 +1559,16 @@ static bool isAnyAccess(AccessKinds AK) { /// Is this an access per the C++ definition? static bool isFormalAccess(AccessKinds AK) { return isAnyAccess(AK) && AK != AK_Construct && AK != AK_Destroy && - AK != AK_IsWithinLifetime; + AK != AK_IsWithinLifetime && AK != AK_Dereference; } -/// Is this kind of axcess valid on an indeterminate object value? +/// Is this kind of access valid on an indeterminate object value? static bool isValidIndeterminateAccess(AccessKinds AK) { switch (AK) { case AK_Read: case AK_Increment: case AK_Decrement: + case AK_Dereference: // These need the object's value. return false; @@ -1733,7 +1735,10 @@ namespace { bool checkNullPointerForFoldAccess(EvalInfo &Info, const Expr *E, AccessKinds AK) { return checkNullPointerDiagnosingWith([&Info, E, AK] { - Info.FFDiag(E, diag::note_constexpr_access_null) << AK; + if (AK == AccessKinds::AK_Dereference) + Info.FFDiag(E, diag::note_constexpr_dereferencing_null); + else + Info.FFDiag(E, diag::note_constexpr_access_null) << AK; }); } @@ -4305,7 +4310,10 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, } if (!LVal.Base) { - Info.FFDiag(E, diag::note_constexpr_access_null) << AK; + if (AK == AccessKinds::AK_Dereference) + Info.FFDiag(E, diag::note_constexpr_dereferencing_null); + else + Info.FFDiag(E, diag::note_constexpr_access_null) << AK; return CompleteObject(); } @@ -4407,8 +4415,9 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, ConstexprVar = VD->isConstexpr(); // Unless we're looking at a local variable or argument in a constexpr call, - // the variable we're reading must be const. - if (!Frame) { + // the variable we're reading must be const (unless we are binding to a + // reference). + if (AK != clang::AK_Dereference && !Frame) { if (IsAccess && isa(VD)) { // Access of a parameter that's not associated with a frame isn't going // to work out, but we can leave it to evaluateVarDeclInit to provide a @@ -4441,7 +4450,8 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, } } else if (!IsAccess) { return CompleteObject(LVal.getLValueBase(), nullptr, BaseType); - } else if (IsConstant && Info.checkingPotentialConstantExpression() && + } else if ((IsConstant || BaseType->isReferenceType()) && + Info.checkingPotentialConstantExpression() && BaseType->isLiteralType(Info.Ctx) && !VD->hasDefinition()) { // This variable might end up being constexpr. Don't diagnose it yet. } else if (IsConstant) { @@ -4472,15 +4482,21 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, } } - if (!evaluateVarDeclInit(Info, E, VD, Frame, LVal.getLValueVersion(), BaseVal)) + // When binding to a reference, the variable does not need to be constexpr + // or have constant initalization. + if (AK != clang::AK_Dereference && + !evaluateVarDeclInit(Info, E, VD, Frame, LVal.getLValueVersion(), + BaseVal)) return CompleteObject(); // If evaluateVarDeclInit sees a constexpr-unknown variable, it returns // a null BaseVal. Any constexpr-unknown variable seen here is an error: // we can't access a constexpr-unknown object. - if (!BaseVal) { - Info.FFDiag(E, diag::note_constexpr_access_unknown_variable, 1) - << AK << VD; - Info.Note(VD->getLocation(), diag::note_declared_at); + if (AK != clang::AK_Dereference && !BaseVal) { + if (!Info.checkingPotentialConstantExpression()) { + Info.FFDiag(E, diag::note_constexpr_access_unknown_variable, 1) + << AK << VD; + Info.Note(VD->getLocation(), diag::note_declared_at); + } return CompleteObject(); } } else if (DynamicAllocLValue DA = LVal.Base.dyn_cast()) { @@ -4491,7 +4507,10 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, } return CompleteObject(LVal.Base, &(*Alloc)->Value, LVal.Base.getDynamicAllocType()); - } else { + } + // When binding to a reference, the variable does not need to be + // within its lifetime. + else if (AK != clang::AK_Dereference) { const Expr *Base = LVal.Base.dyn_cast(); if (!Frame) { @@ -4572,7 +4591,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, NoteLValueLocation(Info, LVal.Base); return CompleteObject(); } - } else { + } else if (AK != clang::AK_Dereference) { BaseVal = Frame->getTemporary(Base, LVal.Base.getVersion()); assert(BaseVal && "missing value for temporary"); } @@ -5200,6 +5219,29 @@ enum EvalStmtResult { ESR_CaseNotFound }; } +/// Evaluates the initializer of a reference. +static bool EvaluateInitForDeclOfReferenceType(EvalInfo &Info, + const ValueDecl *D, + const Expr *Init, LValue &Result, + APValue &Val) { + assert(Init->isGLValue() && D->getType()->isReferenceType()); + // A reference is an lvalue. + if (!EvaluateLValue(Init, Result, Info)) + return false; + // [C++26][decl.ref] + // The object designated by such a glvalue can be outside its lifetime + // Because a null pointer value or a pointer past the end of an object + // does not point to an object, a reference in a well-defined program cannot + // refer to such things; + if (!Result.Designator.Invalid && Result.Designator.isOnePastTheEnd()) { + Info.FFDiag(Init, diag::note_constexpr_access_past_end) << AK_Dereference; + return false; + } + + // Save the result. + Result.moveInto(Val); + return true; +} static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) { if (VD->isInvalidDecl()) @@ -5221,7 +5263,11 @@ static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) { if (InitE->isValueDependent()) return false; - if (!EvaluateInPlace(Val, Info, Result, InitE)) { + // For references to objects, check they do not designate a one-past-the-end + // object. + if (VD->getType()->isReferenceType()) { + return EvaluateInitForDeclOfReferenceType(Info, VD, InitE, Result, Val); + } else if (!EvaluateInPlace(Val, Info, Result, InitE)) { // Wipe out any partially-computed value, to allow tracking that this // evaluation failed. Val = APValue(); @@ -6851,9 +6897,18 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This, ThisOverrideRAII ThisOverride(*Info.CurrentCall, &SubobjectParent, isa(Init)); FullExpressionRAII InitScope(Info); - if (!EvaluateInPlace(*Value, Info, Subobject, Init) || - (FD && FD->isBitField() && - !truncateBitfieldValue(Info, Init, *Value, FD))) { + if (FD && FD->getType()->isReferenceType() && + !FD->getType()->isFunctionReferenceType()) { + LValue Result; + if (!EvaluateInitForDeclOfReferenceType(Info, FD, Init, Result, + *Value)) { + if (!Info.noteFailure()) + return false; + Success = false; + } + } else if (!EvaluateInPlace(*Value, Info, Subobject, Init) || + (FD && FD->isBitField() && + !truncateBitfieldValue(Info, Init, *Value, FD))) { // If we're checking for a potential constant expression, evaluate all // initializers even if some of them fail. if (!Info.noteFailure()) @@ -9287,7 +9342,17 @@ bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { } bool LValueExprEvaluator::VisitUnaryDeref(const UnaryOperator *E) { - return evaluatePointer(E->getSubExpr(), Result); + bool Success = evaluatePointer(E->getSubExpr(), Result); + // [C++26][expr.unary.op] + // If the operand points to an object or function, the result + // denotes that object or function; otherwise, the behavior is undefined. + // Because &(*(type*)0) is a common pattern, we do not fail the evaluation + // immediately. + if (!Success || !E->getType().getNonReferenceType()->isObjectType()) + return Success; + return bool(findCompleteObject(Info, E, AK_Dereference, Result, + E->getType())) || + Info.noteUndefinedBehavior(); } bool LValueExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { @@ -10906,9 +10971,17 @@ bool RecordExprEvaluator::VisitCXXParenListOrInitListExpr( isa(Init)); APValue &FieldVal = Result.getStructField(Field->getFieldIndex()); - if (!EvaluateInPlace(FieldVal, Info, Subobject, Init) || - (Field->isBitField() && !truncateBitfieldValue(Info, Init, - FieldVal, Field))) { + if (Field->getType()->isReferenceType()) { + LValue Result; + if (!EvaluateInitForDeclOfReferenceType(Info, Field, Init, Result, + FieldVal)) { + if (!Info.noteFailure()) + return false; + Success = false; + } + } else if (!EvaluateInPlace(FieldVal, Info, Subobject, Init) || + (Field->isBitField() && + !truncateBitfieldValue(Info, Init, FieldVal, Field))) { if (!Info.noteFailure()) return false; Success = false; @@ -17949,6 +18022,11 @@ bool Expr::isPotentialConstantExprUnevaluated(Expr *E, Info.InConstantContext = true; Info.CheckingPotentialConstantExpression = true; + if (Info.EnableNewConstInterp) { + Info.Ctx.getInterpContext().isPotentialConstantExprUnevaluated(Info, E, FD); + return Diags.empty(); + } + // Fabricate a call stack frame to give the arguments a plausible cover story. CallStackFrame Frame(Info, SourceLocation(), FD, /*This=*/nullptr, /*CallExpr=*/nullptr, CallRef()); @@ -18106,6 +18184,10 @@ bool Expr::EvaluateCharRangeAsString(APValue &Result, bool Expr::tryEvaluateStrLen(uint64_t &Result, ASTContext &Ctx) const { Expr::EvalStatus Status; EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold); + + if (Info.EnableNewConstInterp) + return Info.Ctx.getInterpContext().evaluateStrlen(Info, this, Result); + return EvaluateBuiltinStrLen(this, Result, Info); } diff --git a/clang/lib/AST/FormatString.cpp b/clang/lib/AST/FormatString.cpp index 5d3b56fc4e713..112b756d2be1a 100644 --- a/clang/lib/AST/FormatString.cpp +++ b/clang/lib/AST/FormatString.cpp @@ -320,6 +320,70 @@ bool clang::analyze_format_string::ParseUTF8InvalidSpecifier( // Methods on ArgType. //===----------------------------------------------------------------------===// +static bool namedTypeToLengthModifierKind(ASTContext &Ctx, QualType QT, + LengthModifier::Kind &K) { + if (!Ctx.getLangOpts().C99 && !Ctx.getLangOpts().CPlusPlus) + return false; + for (/**/; const auto *TT = QT->getAs(); QT = TT->desugar()) { + const auto *TD = TT->getDecl(); + const auto *DC = TT->getDecl()->getDeclContext(); + if (DC->isTranslationUnit() || DC->isStdNamespace()) { + StringRef Name = TD->getIdentifier()->getName(); + if (Name == "size_t") { + K = LengthModifier::AsSizeT; + return true; + } else if (Name == "ssize_t" /*Not C99, but common in Unix.*/) { + K = LengthModifier::AsSizeT; + return true; + } else if (Name == "ptrdiff_t") { + K = LengthModifier::AsPtrDiff; + return true; + } else if (Name == "intmax_t") { + K = LengthModifier::AsIntMax; + return true; + } else if (Name == "uintmax_t") { + K = LengthModifier::AsIntMax; + return true; + } + } + } + if (const auto *PST = QT->getAs()) { + using Kind = PredefinedSugarType::Kind; + switch (PST->getKind()) { + case Kind::SizeT: + case Kind::SignedSizeT: + K = LengthModifier::AsSizeT; + return true; + case Kind::PtrdiffT: + K = LengthModifier::AsPtrDiff; + return true; + } + llvm_unreachable("unexpected kind"); + } + return false; +} + +// Check whether T and E are compatible size_t/ptrdiff_t types. E must be +// consistent with LE. +// T is the type of the actual expression in the code to be checked, and E is +// the expected type parsed from the format string. +static clang::analyze_format_string::ArgType::MatchKind +matchesSizeTPtrdiffT(ASTContext &C, QualType T, QualType E) { + using MatchKind = clang::analyze_format_string::ArgType::MatchKind; + + if (!T->isIntegerType()) + return MatchKind::NoMatch; + + if (C.hasSameType(T, E)) + return MatchKind::Match; + + if (C.getCorrespondingSignedType(T.getCanonicalType()) != + C.getCorrespondingSignedType(E.getCanonicalType())) + return MatchKind::NoMatch; + + return MatchKind::NoMatchSignedness; +} + clang::analyze_format_string::ArgType::MatchKind ArgType::matchesType(ASTContext &C, QualType argTy) const { // When using the format attribute in C++, you can receive a function or an @@ -394,6 +458,10 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const { } case SpecificTy: { + if (TK != TypeKind::DontCare) { + return matchesSizeTPtrdiffT(C, argTy, T); + } + if (const EnumType *ETy = argTy->getAs()) { // If the enum is incomplete we know nothing about the underlying type. // Assume that it's 'int'. Do not use the underlying type for a scoped @@ -653,6 +721,12 @@ ArgType::matchesArgType(ASTContext &C, const ArgType &Other) const { if (Left.K == AK::SpecificTy) { if (Right.K == AK::SpecificTy) { + if (Left.TK != TypeKind::DontCare) { + return matchesSizeTPtrdiffT(C, Right.T, Left.T); + } else if (Right.TK != TypeKind::DontCare) { + return matchesSizeTPtrdiffT(C, Left.T, Right.T); + } + auto Canon1 = C.getCanonicalType(Left.T); auto Canon2 = C.getCanonicalType(Right.T); if (Canon1 == Canon2) @@ -706,7 +780,11 @@ QualType ArgType::getRepresentativeType(ASTContext &C) const { Res = C.CharTy; break; case SpecificTy: - Res = T; + if (TK == TypeKind::PtrdiffT || TK == TypeKind::SizeT) + // Using Name as name, so no need to show the uglified name. + Res = T->getCanonicalTypeInternal(); + else + Res = T; break; case CStrTy: Res = C.getPointerType(C.CharTy); @@ -733,7 +811,6 @@ QualType ArgType::getRepresentativeType(ASTContext &C) const { std::string ArgType::getRepresentativeTypeName(ASTContext &C) const { std::string S = getRepresentativeType(C).getAsString(C.getPrintingPolicy()); - std::string Alias; if (Name) { // Use a specific name for this type, e.g. "size_t". @@ -1198,29 +1275,12 @@ FormatSpecifier::getCorrectedLengthModifier() const { return std::nullopt; } -bool FormatSpecifier::namedTypeToLengthModifier(QualType QT, +bool FormatSpecifier::namedTypeToLengthModifier(ASTContext &Ctx, QualType QT, LengthModifier &LM) { - for (/**/; const auto *TT = QT->getAs(); - QT = TT->getDecl()->getUnderlyingType()) { - const TypedefNameDecl *Typedef = TT->getDecl(); - const IdentifierInfo *Identifier = Typedef->getIdentifier(); - if (Identifier->getName() == "size_t") { - LM.setKind(LengthModifier::AsSizeT); - return true; - } else if (Identifier->getName() == "ssize_t") { - // Not C99, but common in Unix. - LM.setKind(LengthModifier::AsSizeT); - return true; - } else if (Identifier->getName() == "intmax_t") { - LM.setKind(LengthModifier::AsIntMax); - return true; - } else if (Identifier->getName() == "uintmax_t") { - LM.setKind(LengthModifier::AsIntMax); - return true; - } else if (Identifier->getName() == "ptrdiff_t") { - LM.setKind(LengthModifier::AsPtrDiff); - return true; - } + if (LengthModifier::Kind Out = LengthModifier::Kind::None; + namedTypeToLengthModifierKind(Ctx, QT, Out)) { + LM.setKind(Out); + return true; } return false; } diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 0520987ce6b3a..2a667934dba42 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -1384,14 +1384,6 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, Out << "sr"; mangleSourceNameWithAbiTags(qualifier->getAsNamespace()); break; - case NestedNameSpecifier::NamespaceAlias: - if (qualifier->getPrefix()) - mangleUnresolvedPrefix(qualifier->getPrefix(), - /*recursive*/ true); - else - Out << "sr"; - mangleSourceNameWithAbiTags(qualifier->getAsNamespaceAlias()); - break; case NestedNameSpecifier::TypeSpec: { const Type *type = qualifier->getAsType(); @@ -2185,11 +2177,7 @@ void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) { llvm_unreachable("Can't mangle __super specifier"); case NestedNameSpecifier::Namespace: - mangleName(qualifier->getAsNamespace()); - return; - - case NestedNameSpecifier::NamespaceAlias: - mangleName(qualifier->getAsNamespaceAlias()->getNamespace()); + mangleName(qualifier->getAsNamespace()->getNamespace()); return; case NestedNameSpecifier::TypeSpec: @@ -2526,6 +2514,10 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, mangleSourceNameWithAbiTags(cast(Ty)->getDecl()); break; + case Type::PredefinedSugar: + mangleType(cast(Ty)->desugar()); + break; + case Type::UnresolvedUsing: mangleSourceNameWithAbiTags( cast(Ty)->getDecl()); diff --git a/clang/lib/AST/NestedNameSpecifier.cpp b/clang/lib/AST/NestedNameSpecifier.cpp index db1ad89565189..56f74b92412d2 100644 --- a/clang/lib/AST/NestedNameSpecifier.cpp +++ b/clang/lib/AST/NestedNameSpecifier.cpp @@ -66,10 +66,9 @@ NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context, return FindOrInsert(Context, Mockup); } -NestedNameSpecifier * -NestedNameSpecifier::Create(const ASTContext &Context, - NestedNameSpecifier *Prefix, - const NamespaceDecl *NS) { +NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context, + NestedNameSpecifier *Prefix, + const NamespaceBaseDecl *NS) { assert(NS && "Namespace cannot be NULL"); assert((!Prefix || (Prefix->getAsType() == nullptr && @@ -78,23 +77,7 @@ NestedNameSpecifier::Create(const ASTContext &Context, NestedNameSpecifier Mockup; Mockup.Prefix.setPointer(Prefix); Mockup.Prefix.setInt(StoredDecl); - Mockup.Specifier = const_cast(NS); - return FindOrInsert(Context, Mockup); -} - -NestedNameSpecifier * -NestedNameSpecifier::Create(const ASTContext &Context, - NestedNameSpecifier *Prefix, - const NamespaceAliasDecl *Alias) { - assert(Alias && "Namespace alias cannot be NULL"); - assert((!Prefix || - (Prefix->getAsType() == nullptr && - Prefix->getAsIdentifier() == nullptr)) && - "Broken nested name specifier"); - NestedNameSpecifier Mockup; - Mockup.Prefix.setPointer(Prefix); - Mockup.Prefix.setInt(StoredDecl); - Mockup.Specifier = const_cast(Alias); + Mockup.Specifier = const_cast(NS); return FindOrInsert(Context, Mockup); } @@ -147,9 +130,7 @@ NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { case StoredDecl: { NamedDecl *ND = static_cast(Specifier); - if (isa(ND)) - return Super; - return isa(ND) ? Namespace : NamespaceAlias; + return isa(ND) ? Super : Namespace; } case StoredTypeSpec: @@ -159,18 +140,11 @@ NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { llvm_unreachable("Invalid NNS Kind!"); } -/// Retrieve the namespace stored in this nested name specifier. -NamespaceDecl *NestedNameSpecifier::getAsNamespace() const { +/// Retrieve the namespace or namespace alias stored in this nested name +/// specifier. +NamespaceBaseDecl *NestedNameSpecifier::getAsNamespace() const { if (Prefix.getInt() == StoredDecl) - return dyn_cast(static_cast(Specifier)); - - return nullptr; -} - -/// Retrieve the namespace alias stored in this nested name specifier. -NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const { - if (Prefix.getInt() == StoredDecl) - return dyn_cast(static_cast(Specifier)); + return dyn_cast(static_cast(Specifier)); return nullptr; } @@ -204,7 +178,6 @@ NestedNameSpecifierDependence NestedNameSpecifier::getDependence() const { } case Namespace: - case NamespaceAlias: case Global: return NestedNameSpecifierDependence::None; @@ -284,7 +257,6 @@ NestedNameSpecifier::translateToType(const ASTContext &Context) const { } case SpecifierKind::Global: case SpecifierKind::Namespace: - case SpecifierKind::NamespaceAlias: case SpecifierKind::Super: // These are not representable as types. return nullptr; @@ -305,16 +277,16 @@ void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy, OS << getAsIdentifier()->getName(); break; - case Namespace: - if (getAsNamespace()->isAnonymousNamespace()) - return; - - OS << getAsNamespace()->getName(); - break; - - case NamespaceAlias: - OS << getAsNamespaceAlias()->getName(); + case Namespace: { + NamespaceBaseDecl *Namespace = getAsNamespace(); + if (const auto *NS = dyn_cast(Namespace)) { + assert(!NS->isAnonymousNamespace()); + OS << NS->getName(); + } else { + OS << cast(Namespace)->getName(); + } break; + } case Global: OS << "::"; @@ -367,7 +339,6 @@ NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Super: // The location of the identifier or namespace name. Length += sizeof(SourceLocation::UIntTy); @@ -418,7 +389,6 @@ SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Super: return SourceRange( LoadSourceLocation(Data, Offset), @@ -569,7 +539,7 @@ void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, } void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, - NamespaceDecl *Namespace, + NamespaceBaseDecl *Namespace, SourceLocation NamespaceLoc, SourceLocation ColonColonLoc) { Representation = NestedNameSpecifier::Create(Context, Representation, @@ -580,17 +550,6 @@ void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); } -void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, - NamespaceAliasDecl *Alias, - SourceLocation AliasLoc, - SourceLocation ColonColonLoc) { - Representation = NestedNameSpecifier::Create(Context, Representation, Alias); - - // Push source-location info into the buffer. - SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity); - SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); -} - void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc) { assert(!Representation && "Already have a nested-name-specifier!?"); @@ -627,7 +586,6 @@ void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context, switch (NNS->getKind()) { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity); break; diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 7fdfcfa3014f3..bd87d4418484b 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -127,9 +127,6 @@ void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) { case NestedNameSpecifier::Namespace: AddDecl(NNS->getAsNamespace()); break; - case NestedNameSpecifier::NamespaceAlias: - AddDecl(NNS->getAsNamespaceAlias()); - break; case NestedNameSpecifier::TypeSpec: AddType(NNS->getAsType()); break; diff --git a/clang/lib/AST/PrintfFormatString.cpp b/clang/lib/AST/PrintfFormatString.cpp index 293164ddac8f8..bcd44f0a85eed 100644 --- a/clang/lib/AST/PrintfFormatString.cpp +++ b/clang/lib/AST/PrintfFormatString.cpp @@ -543,7 +543,8 @@ ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx, case LengthModifier::AsIntMax: return ArgType(Ctx.getIntMaxType(), "intmax_t"); case LengthModifier::AsSizeT: - return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t")); + return ArgType::makeSizeT( + ArgType(Ctx.getSignedSizeType(), "signed size_t")); case LengthModifier::AsInt3264: return Ctx.getTargetInfo().getTriple().isArch64Bit() ? ArgType(Ctx.LongLongTy, "__int64") @@ -626,9 +627,11 @@ ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx, case LengthModifier::AsIntMax: return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t")); case LengthModifier::AsSizeT: - return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t")); + return ArgType::PtrTo(ArgType::makeSizeT( + ArgType(Ctx.getSignedSizeType(), "signed size_t"))); case LengthModifier::AsPtrDiff: - return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); + return ArgType::PtrTo(ArgType::makePtrdiffT( + ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"))); case LengthModifier::AsLongDouble: return ArgType(); // FIXME: Is this a known extension? case LengthModifier::AsAllocate: @@ -917,7 +920,7 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99. if (LangOpt.C99 || LangOpt.CPlusPlus11) - namedTypeToLengthModifier(QT, LM); + namedTypeToLengthModifier(Ctx, QT, LM); // If fixing the length modifier was enough, we might be done. if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) { diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp index 39703d6d7b882..b43bcd8d1f1c1 100644 --- a/clang/lib/AST/QualTypeNames.cpp +++ b/clang/lib/AST/QualTypeNames.cpp @@ -218,16 +218,7 @@ static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier( return Scope; case NestedNameSpecifier::Namespace: return TypeName::createNestedNameSpecifier( - Ctx, Scope->getAsNamespace(), WithGlobalNsPrefix); - case NestedNameSpecifier::NamespaceAlias: - // Namespace aliases are only valid for the duration of the - // scope where they were introduced, and therefore are often - // invalid at the end of the TU. So use the namespace name more - // likely to be valid at the end of the TU. - return TypeName::createNestedNameSpecifier( - Ctx, - Scope->getAsNamespaceAlias()->getNamespace()->getCanonicalDecl(), - WithGlobalNsPrefix); + Ctx, Scope->getAsNamespace()->getNamespace(), WithGlobalNsPrefix); case NestedNameSpecifier::Identifier: // A function or some other construct that makes it un-namable // at the end of the TU. Skip the current component of the name, diff --git a/clang/lib/AST/ScanfFormatString.cpp b/clang/lib/AST/ScanfFormatString.cpp index 7ee21c8c61954..1227edd47d13d 100644 --- a/clang/lib/AST/ScanfFormatString.cpp +++ b/clang/lib/AST/ScanfFormatString.cpp @@ -251,9 +251,11 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const { case LengthModifier::AsIntMax: return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t")); case LengthModifier::AsSizeT: - return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t")); + return ArgType::PtrTo(ArgType::makeSizeT( + ArgType(Ctx.getSignedSizeType(), "signed size_t"))); case LengthModifier::AsPtrDiff: - return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); + return ArgType::PtrTo(ArgType::makePtrdiffT( + ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"))); case LengthModifier::AsLongDouble: // GNU extension. return ArgType::PtrTo(Ctx.LongLongTy); @@ -292,10 +294,11 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const { case LengthModifier::AsIntMax: return ArgType::PtrTo(ArgType(Ctx.getUIntMaxType(), "uintmax_t")); case LengthModifier::AsSizeT: - return ArgType::PtrTo(ArgType(Ctx.getSizeType(), "size_t")); - case LengthModifier::AsPtrDiff: return ArgType::PtrTo( - ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t")); + ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t"))); + case LengthModifier::AsPtrDiff: + return ArgType::PtrTo(ArgType::makePtrdiffT( + ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"))); case LengthModifier::AsLongDouble: // GNU extension. return ArgType::PtrTo(Ctx.UnsignedLongLongTy); @@ -390,9 +393,11 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const { case LengthModifier::AsIntMax: return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t")); case LengthModifier::AsSizeT: - return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t")); + return ArgType::PtrTo(ArgType::makeSizeT( + ArgType(Ctx.getSignedSizeType(), "signed size_t"))); case LengthModifier::AsPtrDiff: - return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); + return ArgType::PtrTo(ArgType::makePtrdiffT( + ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"))); case LengthModifier::AsLongDouble: return ArgType(); // FIXME: Is this a known extension? case LengthModifier::AsAllocate: @@ -501,7 +506,7 @@ bool ScanfSpecifier::fixType(QualType QT, QualType RawQT, // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99. if (LangOpt.C99 || LangOpt.CPlusPlus11) - namedTypeToLengthModifier(PT, LM); + namedTypeToLengthModifier(Ctx, PT, LM); // If fixing the length modifier was enough, we are done. if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) { diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index be02bdde38a3d..6ba5ec89964a9 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -610,7 +610,7 @@ void StmtPrinter::VisitObjCAtTryStmt(ObjCAtTryStmt *Node) { } } - if (auto *FS = static_cast(Node->getFinallyStmt())) { + if (ObjCAtFinallyStmt *FS = Node->getFinallyStmt()) { Indent() << "@finally"; if (auto *CS = dyn_cast(FS->getFinallyBody())) { PrintRawCompoundStmt(CS); diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 9d7c2757d6ee4..6b524cfcd2d71 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -843,7 +843,10 @@ void TextNodeDumper::Visit(const APValue &Value, QualType Ty) { } ColorScope Color(OS, ShowColors, DeclNameColor); - OS << Value.getMemberPointerDecl()->getDeclName(); + if (const ValueDecl *MemDecl = Value.getMemberPointerDecl()) + OS << MemDecl->getDeclName(); + else + OS << "null"; return; } case APValue::AddrLabelDiff: @@ -1050,10 +1053,6 @@ void clang::TextNodeDumper::dumpNestedNameSpecifier(const NestedNameSpecifier *N OS << " "; // "Namespace" is printed as the decl kind. dumpBareDeclRef(NNS->getAsNamespace()); break; - case NestedNameSpecifier::NamespaceAlias: - OS << " "; // "NamespaceAlias" is printed as the decl kind. - dumpBareDeclRef(NNS->getAsNamespaceAlias()); - break; case NestedNameSpecifier::TypeSpec: OS << " TypeSpec"; dumpType(QualType(NNS->getAsType(), 0)); diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index e5a1ab2ff8906..7444a2f90c5dd 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -5613,3 +5613,15 @@ HLSLAttributedResourceType::findHandleTypeOnResource(const Type *RT) { } return nullptr; } + +StringRef PredefinedSugarType::getName(Kind KD) { + switch (KD) { + case Kind::SizeT: + return "__size_t"; + case Kind::SignedSizeT: + return "__signed_size_t"; + case Kind::PtrdiffT: + return "__ptrdiff_t"; + } + llvm_unreachable("unexpected kind"); +} diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 818d2139628e3..deb453fe6ee75 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -248,6 +248,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::BTFTagAttributed: case Type::HLSLAttributedResource: case Type::HLSLInlineSpirv: + case Type::PredefinedSugar: CanPrefixQualifiers = true; break; @@ -1417,6 +1418,15 @@ void TypePrinter::printDependentBitIntBefore(const DependentBitIntType *T, void TypePrinter::printDependentBitIntAfter(const DependentBitIntType *T, raw_ostream &OS) {} +void TypePrinter::printPredefinedSugarBefore(const PredefinedSugarType *T, + raw_ostream &OS) { + OS << T->getIdentifier()->getName(); + spaceBeforePlaceHolder(OS); +} + +void TypePrinter::printPredefinedSugarAfter(const PredefinedSugarType *T, + raw_ostream &OS) {} + /// Appends the given scope to the end of a string. void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS, DeclarationName NameInScope) { diff --git a/clang/lib/Analysis/LifetimeSafety.cpp b/clang/lib/Analysis/LifetimeSafety.cpp index bf67bea6c9933..ae6ec9f76cbf6 100644 --- a/clang/lib/Analysis/LifetimeSafety.cpp +++ b/clang/lib/Analysis/LifetimeSafety.cpp @@ -18,13 +18,20 @@ #include "llvm/ADT/ImmutableMap.h" #include "llvm/ADT/ImmutableSet.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Debug.h" #include "llvm/Support/TimeProfiler.h" #include -namespace clang { +namespace clang::lifetimes { +namespace internal { namespace { +template +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) { + return OS << ID.Value; +} +} // namespace /// Represents the storage location being borrowed, e.g., a specific stack /// variable. @@ -35,32 +42,6 @@ struct AccessPath { AccessPath(const clang::ValueDecl *D) : D(D) {} }; -/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type. -/// Used for giving ID to loans and origins. -template struct ID { - uint32_t Value = 0; - - bool operator==(const ID &Other) const { return Value == Other.Value; } - bool operator!=(const ID &Other) const { return !(*this == Other); } - bool operator<(const ID &Other) const { return Value < Other.Value; } - ID operator++(int) { - ID Tmp = *this; - ++Value; - return Tmp; - } - void Profile(llvm::FoldingSetNodeID &IDBuilder) const { - IDBuilder.AddInteger(Value); - } -}; - -template -inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) { - return OS << ID.Value; -} - -using LoanID = ID; -using OriginID = ID; - /// Information about a single borrow, or "Loan". A loan is created when a /// reference or pointer is created. struct Loan { @@ -222,7 +203,9 @@ class Fact { /// An origin is propagated from a source to a destination (e.g., p = q). AssignOrigin, /// An origin escapes the function by flowing into the return value. - ReturnOfOrigin + ReturnOfOrigin, + /// A marker for a specific point in the code, for testing. + TestPoint, }; private: @@ -309,6 +292,24 @@ class ReturnOfOriginFact : public Fact { } }; +/// A dummy-fact used to mark a specific point in the code for testing. +/// It is generated by recognizing a `void("__lifetime_test_point_...")` cast. +class TestPointFact : public Fact { + StringRef Annotation; + +public: + static bool classof(const Fact *F) { return F->getKind() == Kind::TestPoint; } + + explicit TestPointFact(StringRef Annotation) + : Fact(Kind::TestPoint), Annotation(Annotation) {} + + StringRef getAnnotation() const { return Annotation; } + + void dump(llvm::raw_ostream &OS) const override { + OS << "TestPoint (Annotation: \"" << getAnnotation() << "\")\n"; + } +}; + class FactManager { public: llvm::ArrayRef getFacts(const CFGBlock *B) const { @@ -362,6 +363,7 @@ class FactManager { }; class FactGenerator : public ConstStmtVisitor { + using Base = ConstStmtVisitor; public: FactGenerator(FactManager &FactMgr, AnalysisDeclContext &AC) @@ -457,6 +459,15 @@ class FactGenerator : public ConstStmtVisitor { } } + void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *FCE) { + // Check if this is a test point marker. If so, we are done with this + // expression. + if (VisitTestPoint(FCE)) + return; + // Visit as normal otherwise. + Base::VisitCXXFunctionalCastExpr(FCE); + } + private: // Check if a type has an origin. bool hasOrigin(QualType QT) { return QT->isPointerOrReferenceType(); } @@ -490,101 +501,267 @@ class FactGenerator : public ConstStmtVisitor { } } + /// Checks if the expression is a `void("__lifetime_test_point_...")` cast. + /// If so, creates a `TestPointFact` and returns true. + bool VisitTestPoint(const CXXFunctionalCastExpr *FCE) { + if (!FCE->getType()->isVoidType()) + return false; + + const auto *SubExpr = FCE->getSubExpr()->IgnoreParenImpCasts(); + if (const auto *SL = dyn_cast(SubExpr)) { + llvm::StringRef LiteralValue = SL->getString(); + const std::string Prefix = "__lifetime_test_point_"; + + if (LiteralValue.starts_with(Prefix)) { + StringRef Annotation = LiteralValue.drop_front(Prefix.length()); + CurrentBlockFacts.push_back( + FactMgr.createFact(Annotation)); + return true; + } + } + return false; + } + FactManager &FactMgr; AnalysisDeclContext &AC; llvm::SmallVector CurrentBlockFacts; }; // ========================================================================= // -// The Dataflow Lattice +// Generic Dataflow Analysis +// ========================================================================= // + +enum class Direction { Forward, Backward }; + +/// A `ProgramPoint` identifies a location in the CFG by pointing to a specific +/// `Fact`. identified by a lifetime-related event (`Fact`). +/// +/// A `ProgramPoint` has "after" semantics: it represents the location +/// immediately after its corresponding `Fact`. +using ProgramPoint = const Fact *; + +/// A generic, policy-based driver for dataflow analyses. It combines +/// the dataflow runner and the transferer logic into a single class hierarchy. +/// +/// The derived class is expected to provide: +/// - A `Lattice` type. +/// - `StringRef getAnalysisName() const` +/// - `Lattice getInitialState();` The initial state of the analysis. +/// - `Lattice join(Lattice, Lattice);` Merges states from multiple CFG paths. +/// - `Lattice transfer(Lattice, const FactType&);` Defines how a single +/// lifetime-relevant `Fact` transforms the lattice state. Only overloads +/// for facts relevant to the analysis need to be implemented. +/// +/// \tparam Derived The CRTP derived class that implements the specific +/// analysis. +/// \tparam LatticeType The dataflow lattice used by the analysis. +/// \tparam Dir The direction of the analysis (Forward or Backward). +/// TODO: Maybe use the dataflow framework! The framework might need changes +/// to support the current comparison done at block-entry. +template +class DataflowAnalysis { +public: + using Lattice = LatticeType; + using Base = DataflowAnalysis; + +private: + const CFG &Cfg; + AnalysisDeclContext &AC; + + /// The dataflow state before a basic block is processed. + llvm::DenseMap InStates; + /// The dataflow state after a basic block is processed. + llvm::DenseMap OutStates; + /// The dataflow state at a Program Point. + /// In a forward analysis, this is the state after the Fact at that point has + /// been applied, while in a backward analysis, it is the state before. + llvm::DenseMap PerPointStates; + + static constexpr bool isForward() { return Dir == Direction::Forward; } + +protected: + FactManager &AllFacts; + + explicit DataflowAnalysis(const CFG &C, AnalysisDeclContext &AC, + FactManager &F) + : Cfg(C), AC(AC), AllFacts(F) {} + +public: + void run() { + Derived &D = static_cast(*this); + llvm::TimeTraceScope Time(D.getAnalysisName()); + + using Worklist = + std::conditional_t; + Worklist W(Cfg, AC); + + const CFGBlock *Start = isForward() ? &Cfg.getEntry() : &Cfg.getExit(); + InStates[Start] = D.getInitialState(); + W.enqueueBlock(Start); + + llvm::SmallBitVector Visited(Cfg.getNumBlockIDs() + 1); + + while (const CFGBlock *B = W.dequeue()) { + Lattice StateIn = getInState(B); + Lattice StateOut = transferBlock(B, StateIn); + OutStates[B] = StateOut; + Visited.set(B->getBlockID()); + for (const CFGBlock *AdjacentB : isForward() ? B->succs() : B->preds()) { + Lattice OldInState = getInState(AdjacentB); + Lattice NewInState = D.join(OldInState, StateOut); + // Enqueue the adjacent block if its in-state has changed or if we have + // never visited it. + if (!Visited.test(AdjacentB->getBlockID()) || + NewInState != OldInState) { + InStates[AdjacentB] = NewInState; + W.enqueueBlock(AdjacentB); + } + } + } + } + + Lattice getState(ProgramPoint P) const { return PerPointStates.lookup(P); } + + Lattice getInState(const CFGBlock *B) const { return InStates.lookup(B); } + + Lattice getOutState(const CFGBlock *B) const { return OutStates.lookup(B); } + + void dump() const { + const Derived *D = static_cast(this); + llvm::dbgs() << "==========================================\n"; + llvm::dbgs() << D->getAnalysisName() << " results:\n"; + llvm::dbgs() << "==========================================\n"; + const CFGBlock &B = isForward() ? Cfg.getExit() : Cfg.getEntry(); + getOutState(&B).dump(llvm::dbgs()); + } + +private: + /// Computes the state at one end of a block by applying all its facts + /// sequentially to a given state from the other end. + Lattice transferBlock(const CFGBlock *Block, Lattice State) { + auto Facts = AllFacts.getFacts(Block); + if constexpr (isForward()) { + for (const Fact *F : Facts) { + State = transferFact(State, F); + PerPointStates[F] = State; + } + } else { + for (const Fact *F : llvm::reverse(Facts)) { + // In backward analysis, capture the state before applying the fact. + PerPointStates[F] = State; + State = transferFact(State, F); + } + } + return State; + } + + Lattice transferFact(Lattice In, const Fact *F) { + assert(F); + Derived *D = static_cast(this); + switch (F->getKind()) { + case Fact::Kind::Issue: + return D->transfer(In, *F->getAs()); + case Fact::Kind::Expire: + return D->transfer(In, *F->getAs()); + case Fact::Kind::AssignOrigin: + return D->transfer(In, *F->getAs()); + case Fact::Kind::ReturnOfOrigin: + return D->transfer(In, *F->getAs()); + case Fact::Kind::TestPoint: + return D->transfer(In, *F->getAs()); + } + llvm_unreachable("Unknown fact kind"); + } + +public: + Lattice transfer(Lattice In, const IssueFact &) { return In; } + Lattice transfer(Lattice In, const ExpireFact &) { return In; } + Lattice transfer(Lattice In, const AssignOriginFact &) { return In; } + Lattice transfer(Lattice In, const ReturnOfOriginFact &) { return In; } + Lattice transfer(Lattice In, const TestPointFact &) { return In; } +}; + +namespace utils { + +/// Computes the union of two ImmutableSets. +template +static llvm::ImmutableSet join(llvm::ImmutableSet A, + llvm::ImmutableSet B, + typename llvm::ImmutableSet::Factory &F) { + if (A.getHeight() < B.getHeight()) + std::swap(A, B); + for (const T &E : B) + A = F.add(A, E); + return A; +} + +/// Computes the key-wise union of two ImmutableMaps. +// TODO(opt): This key-wise join is a performance bottleneck. A more +// efficient merge could be implemented using a Patricia Trie or HAMT +// instead of the current AVL-tree-based ImmutableMap. +template +static llvm::ImmutableMap +join(llvm::ImmutableMap A, llvm::ImmutableMap B, + typename llvm::ImmutableMap::Factory &F, Joiner joinValues) { + if (A.getHeight() < B.getHeight()) + std::swap(A, B); + + // For each element in B, join it with the corresponding element in A + // (or with an empty value if it doesn't exist in A). + for (const auto &Entry : B) { + const K &Key = Entry.first; + const V &ValB = Entry.second; + if (const V *ValA = A.lookup(Key)) + A = F.add(A, Key, joinValues(*ValA, ValB)); + else + A = F.add(A, Key, ValB); + } + return A; +} +} // namespace utils + +// ========================================================================= // +// Loan Propagation Analysis // ========================================================================= // -// Using LLVM's immutable collections is efficient for dataflow analysis -// as it avoids deep copies during state transitions. -// TODO(opt): Consider using a bitset to represent the set of loans. -using LoanSet = llvm::ImmutableSet; using OriginLoanMap = llvm::ImmutableMap; /// An object to hold the factories for immutable collections, ensuring /// that all created states share the same underlying memory management. struct LifetimeFactory { OriginLoanMap::Factory OriginMapFactory; - LoanSet::Factory LoanSetFact; + LoanSet::Factory LoanSetFactory; /// Creates a singleton set containing only the given loan ID. LoanSet createLoanSet(LoanID LID) { - return LoanSetFact.add(LoanSetFact.getEmptySet(), LID); + return LoanSetFactory.add(LoanSetFactory.getEmptySet(), LID); } }; -/// LifetimeLattice represents the state of our analysis at a given program -/// point. It is an immutable object, and all operations produce a new -/// instance rather than modifying the existing one. -struct LifetimeLattice { +/// Represents the dataflow lattice for loan propagation. +/// +/// This lattice tracks which loans each origin may hold at a given program +/// point.The lattice has a finite height: An origin's loan set is bounded by +/// the total number of loans in the function. +/// TODO(opt): To reduce the lattice size, propagate origins of declarations, +/// not expressions, because expressions are not visible across blocks. +struct LoanPropagationLattice { /// The map from an origin to the set of loans it contains. - /// The lattice has a finite height: An origin's loan set is bounded by the - /// total number of loans in the function. - /// TODO(opt): To reduce the lattice size, propagate origins of declarations, - /// not expressions, because expressions are not visible across blocks. OriginLoanMap Origins = OriginLoanMap(nullptr); - explicit LifetimeLattice(const OriginLoanMap &S) : Origins(S) {} - LifetimeLattice() = default; + explicit LoanPropagationLattice(const OriginLoanMap &S) : Origins(S) {} + LoanPropagationLattice() = default; - bool operator==(const LifetimeLattice &Other) const { + bool operator==(const LoanPropagationLattice &Other) const { return Origins == Other.Origins; } - bool operator!=(const LifetimeLattice &Other) const { + bool operator!=(const LoanPropagationLattice &Other) const { return !(*this == Other); } - LoanSet getLoans(OriginID OID) const { - if (auto *Loans = Origins.lookup(OID)) - return *Loans; - return LoanSet(nullptr); - } - - /// Computes the union of two lattices by performing a key-wise join of - /// their OriginLoanMaps. - // TODO(opt): This key-wise join is a performance bottleneck. A more - // efficient merge could be implemented using a Patricia Trie or HAMT - // instead of the current AVL-tree-based ImmutableMap. - // TODO(opt): Keep the state small by removing origins which become dead. - LifetimeLattice join(const LifetimeLattice &Other, - LifetimeFactory &Factory) const { - /// Merge the smaller map into the larger one ensuring we iterate over the - /// smaller map. - if (Origins.getHeight() < Other.Origins.getHeight()) - return Other.join(*this, Factory); - - OriginLoanMap JoinedState = Origins; - // For each origin in the other map, union its loan set with ours. - for (const auto &Entry : Other.Origins) { - OriginID OID = Entry.first; - LoanSet OtherLoanSet = Entry.second; - JoinedState = Factory.OriginMapFactory.add( - JoinedState, OID, join(getLoans(OID), OtherLoanSet, Factory)); - } - return LifetimeLattice(JoinedState); - } - - LoanSet join(LoanSet a, LoanSet b, LifetimeFactory &Factory) const { - /// Merge the smaller set into the larger one ensuring we iterate over the - /// smaller set. - if (a.getHeight() < b.getHeight()) - std::swap(a, b); - LoanSet Result = a; - for (LoanID LID : b) { - /// TODO(opt): Profiling shows that this loop is a major performance - /// bottleneck. Investigate using a BitVector to represent the set of - /// loans for improved join performance. - Result = Factory.LoanSetFact.add(Result, LID); - } - return Result; - } - void dump(llvm::raw_ostream &OS) const { - OS << "LifetimeLattice State:\n"; + OS << "LoanPropagationLattice State:\n"; if (Origins.isEmpty()) OS << " \n"; for (const auto &Entry : Origins) { @@ -596,155 +773,93 @@ struct LifetimeLattice { } }; -// ========================================================================= // -// The Transfer Function -// ========================================================================= // -class Transferer { - FactManager &AllFacts; +/// The analysis that tracks which loans belong to which origins. +class LoanPropagationAnalysis + : public DataflowAnalysis { + LifetimeFactory &Factory; public: - explicit Transferer(FactManager &F, LifetimeFactory &Factory) - : AllFacts(F), Factory(Factory) {} - - /// Computes the exit state of a block by applying all its facts sequentially - /// to a given entry state. - /// TODO: We might need to store intermediate states per-fact in the block for - /// later analysis. - LifetimeLattice transferBlock(const CFGBlock *Block, - LifetimeLattice EntryState) { - LifetimeLattice BlockState = EntryState; - llvm::ArrayRef Facts = AllFacts.getFacts(Block); - - for (const Fact *F : Facts) { - BlockState = transferFact(BlockState, F); - } - return BlockState; - } + LoanPropagationAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F, + LifetimeFactory &Factory) + : DataflowAnalysis(C, AC, F), Factory(Factory) {} -private: - LifetimeLattice transferFact(LifetimeLattice In, const Fact *F) { - switch (F->getKind()) { - case Fact::Kind::Issue: - return transfer(In, *F->getAs()); - case Fact::Kind::AssignOrigin: - return transfer(In, *F->getAs()); - // Expire and ReturnOfOrigin facts don't modify the Origins and the State. - case Fact::Kind::Expire: - case Fact::Kind::ReturnOfOrigin: - return In; - } - llvm_unreachable("Unknown fact kind"); + using Base::transfer; + + StringRef getAnalysisName() const { return "LoanPropagation"; } + + Lattice getInitialState() { return Lattice{}; } + + /// Merges two lattices by taking the union of loans for each origin. + // TODO(opt): Keep the state small by removing origins which become dead. + Lattice join(Lattice A, Lattice B) { + OriginLoanMap JoinedOrigins = + utils::join(A.Origins, B.Origins, Factory.OriginMapFactory, + [this](LoanSet S1, LoanSet S2) { + return utils::join(S1, S2, Factory.LoanSetFactory); + }); + return Lattice(JoinedOrigins); } /// A new loan is issued to the origin. Old loans are erased. - LifetimeLattice transfer(LifetimeLattice In, const IssueFact &F) { + Lattice transfer(Lattice In, const IssueFact &F) { OriginID OID = F.getOriginID(); LoanID LID = F.getLoanID(); - return LifetimeLattice(Factory.OriginMapFactory.add( + return LoanPropagationLattice(Factory.OriginMapFactory.add( In.Origins, OID, Factory.createLoanSet(LID))); } /// The destination origin's loan set is replaced by the source's. /// This implicitly "resets" the old loans of the destination. - LifetimeLattice transfer(LifetimeLattice InState, const AssignOriginFact &F) { + Lattice transfer(Lattice In, const AssignOriginFact &F) { OriginID DestOID = F.getDestOriginID(); OriginID SrcOID = F.getSrcOriginID(); - LoanSet SrcLoans = InState.getLoans(SrcOID); - return LifetimeLattice( - Factory.OriginMapFactory.add(InState.Origins, DestOID, SrcLoans)); + LoanSet SrcLoans = getLoans(In, SrcOID); + return LoanPropagationLattice( + Factory.OriginMapFactory.add(In.Origins, DestOID, SrcLoans)); } -}; -// ========================================================================= // -// Dataflow analysis -// ========================================================================= // - -/// Drives the intra-procedural dataflow analysis. -/// -/// Orchestrates the analysis by iterating over the CFG using a worklist -/// algorithm. It computes a fixed point by propagating the LifetimeLattice -/// state through each block until the state no longer changes. -/// TODO: Maybe use the dataflow framework! The framework might need changes -/// to support the current comparison done at block-entry. -class LifetimeDataflow { - const CFG &Cfg; - AnalysisDeclContext &AC; - LifetimeFactory LifetimeFact; - - Transferer Xfer; - - /// Stores the merged analysis state at the entry of each CFG block. - llvm::DenseMap BlockEntryStates; - /// Stores the analysis state at the exit of each CFG block, after the - /// transfer function has been applied. - llvm::DenseMap BlockExitStates; - -public: - LifetimeDataflow(const CFG &C, FactManager &FS, AnalysisDeclContext &AC) - : Cfg(C), AC(AC), Xfer(FS, LifetimeFact) {} - - void run() { - llvm::TimeTraceScope TimeProfile("Lifetime Dataflow"); - ForwardDataflowWorklist Worklist(Cfg, AC); - const CFGBlock *Entry = &Cfg.getEntry(); - BlockEntryStates[Entry] = LifetimeLattice{}; - Worklist.enqueueBlock(Entry); - while (const CFGBlock *B = Worklist.dequeue()) { - LifetimeLattice EntryState = getEntryState(B); - LifetimeLattice ExitState = Xfer.transferBlock(B, EntryState); - BlockExitStates[B] = ExitState; - - for (const CFGBlock *Successor : B->succs()) { - auto SuccIt = BlockEntryStates.find(Successor); - LifetimeLattice OldSuccEntryState = (SuccIt != BlockEntryStates.end()) - ? SuccIt->second - : LifetimeLattice{}; - LifetimeLattice NewSuccEntryState = - OldSuccEntryState.join(ExitState, LifetimeFact); - // Enqueue the successor if its entry state has changed. - // TODO(opt): Consider changing 'join' to report a change if != - // comparison is found expensive. - if (SuccIt == BlockEntryStates.end() || - NewSuccEntryState != OldSuccEntryState) { - BlockEntryStates[Successor] = NewSuccEntryState; - Worklist.enqueueBlock(Successor); - } - } - } - } - - void dump() const { - llvm::dbgs() << "==========================================\n"; - llvm::dbgs() << " Dataflow results:\n"; - llvm::dbgs() << "==========================================\n"; - const CFGBlock &B = Cfg.getExit(); - getExitState(&B).dump(llvm::dbgs()); - } - - LifetimeLattice getEntryState(const CFGBlock *B) const { - return BlockEntryStates.lookup(B); + LoanSet getLoans(OriginID OID, ProgramPoint P) { + return getLoans(getState(P), OID); } - LifetimeLattice getExitState(const CFGBlock *B) const { - return BlockExitStates.lookup(B); +private: + LoanSet getLoans(Lattice L, OriginID OID) { + if (auto *Loans = L.Origins.lookup(OID)) + return *Loans; + return Factory.LoanSetFactory.getEmptySet(); } }; // ========================================================================= // -// TODO: Analysing dataflow results and error reporting. +// TODO: +// - Modify loan expiry analysis to answer `bool isExpired(Loan L, Point P)` +// - Modify origin liveness analysis to answer `bool isLive(Origin O, Point P)` +// - Using the above three to perform the final error reporting. // ========================================================================= // -} // anonymous namespace -void runLifetimeSafetyAnalysis(const DeclContext &DC, const CFG &Cfg, - AnalysisDeclContext &AC) { +// ========================================================================= // +// LifetimeSafetyAnalysis Class Implementation +// ========================================================================= // + +// We need this here for unique_ptr with forward declared class. +LifetimeSafetyAnalysis::~LifetimeSafetyAnalysis() = default; + +LifetimeSafetyAnalysis::LifetimeSafetyAnalysis(AnalysisDeclContext &AC) + : AC(AC), Factory(std::make_unique()), + FactMgr(std::make_unique()) {} + +void LifetimeSafetyAnalysis::run() { llvm::TimeTraceScope TimeProfile("LifetimeSafetyAnalysis"); + + const CFG &Cfg = *AC.getCFG(); DEBUG_WITH_TYPE("PrintCFG", Cfg.dump(AC.getASTContext().getLangOpts(), /*ShowColors=*/true)); - FactManager FactMgr; - FactGenerator FactGen(FactMgr, AC); + + FactGenerator FactGen(*FactMgr, AC); FactGen.run(); - DEBUG_WITH_TYPE("LifetimeFacts", FactMgr.dump(Cfg, AC)); + DEBUG_WITH_TYPE("LifetimeFacts", FactMgr->dump(Cfg, AC)); /// TODO(opt): Consider optimizing individual blocks before running the /// dataflow analysis. @@ -755,8 +870,56 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const CFG &Cfg, /// blocks; only Decls are visible. Therefore, loans in a block that /// never reach an Origin associated with a Decl can be safely dropped by /// the analysis. - LifetimeDataflow Dataflow(Cfg, FactMgr, AC); - Dataflow.run(); - DEBUG_WITH_TYPE("LifetimeDataflow", Dataflow.dump()); + LoanPropagation = + std::make_unique(Cfg, AC, *FactMgr, *Factory); + LoanPropagation->run(); +} + +LoanSet LifetimeSafetyAnalysis::getLoansAtPoint(OriginID OID, + ProgramPoint PP) const { + assert(LoanPropagation && "Analysis has not been run."); + return LoanPropagation->getLoans(OID, PP); +} + +std::optional +LifetimeSafetyAnalysis::getOriginIDForDecl(const ValueDecl *D) const { + assert(FactMgr && "FactManager not initialized"); + // This assumes the OriginManager's `get` can find an existing origin. + // We might need a `find` method on OriginManager to avoid `getOrCreate` logic + // in a const-query context if that becomes an issue. + return FactMgr->getOriginMgr().get(*D); +} + +std::vector +LifetimeSafetyAnalysis::getLoanIDForVar(const VarDecl *VD) const { + assert(FactMgr && "FactManager not initialized"); + std::vector Result; + for (const Loan &L : FactMgr->getLoanMgr().getLoans()) + if (L.Path.D == VD) + Result.push_back(L.ID); + return Result; +} + +llvm::StringMap LifetimeSafetyAnalysis::getTestPoints() const { + assert(FactMgr && "FactManager not initialized"); + llvm::StringMap AnnotationToPointMap; + for (const CFGBlock *Block : *AC.getCFG()) { + for (const Fact *F : FactMgr->getFacts(Block)) { + if (const auto *TPF = F->getAs()) { + StringRef PointName = TPF->getAnnotation(); + assert(AnnotationToPointMap.find(PointName) == + AnnotationToPointMap.end() && + "more than one test points with the same name"); + AnnotationToPointMap[PointName] = F; + } + } + } + return AnnotationToPointMap; +} +} // namespace internal + +void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC) { + internal::LifetimeSafetyAnalysis Analysis(AC); + Analysis.run(); } -} // namespace clang +} // namespace clang::lifetimes diff --git a/clang/lib/Analysis/plugins/CheckerDependencyHandling/CheckerDependencyHandling.cpp b/clang/lib/Analysis/plugins/CheckerDependencyHandling/CheckerDependencyHandling.cpp index aacb886f6e122..518f9e7ddf347 100644 --- a/clang/lib/Analysis/plugins/CheckerDependencyHandling/CheckerDependencyHandling.cpp +++ b/clang/lib/Analysis/plugins/CheckerDependencyHandling/CheckerDependencyHandling.cpp @@ -2,6 +2,9 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h" +// This barebones plugin is used by clang/test/Analysis/checker-plugins.c +// to test dependency handling among checkers loaded from plugins. + using namespace clang; using namespace ento; @@ -15,12 +18,12 @@ struct DependendentChecker : public Checker { } // end anonymous namespace // Register plugin! -extern "C" void clang_registerCheckers(CheckerRegistry ®istry) { - registry.addChecker("example.Dependency", "", ""); - registry.addChecker("example.DependendentChecker", "", - ""); +extern "C" void clang_registerCheckers(CheckerRegistry &Registry) { + Registry.addChecker("example.Dependency", "MockDescription"); + Registry.addChecker("example.DependendentChecker", + "MockDescription"); - registry.addDependency("example.DependendentChecker", "example.Dependency"); + Registry.addDependency("example.DependendentChecker", "example.Dependency"); } extern "C" const char clang_analyzerAPIVersionString[] = diff --git a/clang/lib/Analysis/plugins/CheckerOptionHandling/CheckerOptionHandling.cpp b/clang/lib/Analysis/plugins/CheckerOptionHandling/CheckerOptionHandling.cpp index 82c1058242551..2adb9348f6715 100644 --- a/clang/lib/Analysis/plugins/CheckerOptionHandling/CheckerOptionHandling.cpp +++ b/clang/lib/Analysis/plugins/CheckerOptionHandling/CheckerOptionHandling.cpp @@ -5,6 +5,9 @@ using namespace clang; using namespace ento; +// This barebones plugin is used by clang/test/Analysis/checker-plugins.c +// to test option handling on checkers loaded from plugins. + namespace { struct MyChecker : public Checker { void checkBeginFunction(CheckerContext &Ctx) const {} @@ -25,13 +28,11 @@ bool shouldRegisterMyChecker(const CheckerManager &mgr) { return true; } } // end anonymous namespace // Register plugin! -extern "C" void clang_registerCheckers(CheckerRegistry ®istry) { - registry.addChecker(registerMyChecker, shouldRegisterMyChecker, - "example.MyChecker", "Example Description", - "example.mychecker.documentation.nonexistent.html", - /*isHidden*/false); +extern "C" void clang_registerCheckers(CheckerRegistry &Registry) { + Registry.addChecker(registerMyChecker, shouldRegisterMyChecker, + "example.MyChecker", "Example Description"); - registry.addCheckerOption(/*OptionType*/ "bool", + Registry.addCheckerOption(/*OptionType*/ "bool", /*CheckerFullName*/ "example.MyChecker", /*OptionName*/ "ExampleOption", /*DefaultValStr*/ "false", diff --git a/clang/lib/Analysis/plugins/SampleAnalyzer/MainCallChecker.cpp b/clang/lib/Analysis/plugins/SampleAnalyzer/MainCallChecker.cpp index fd210d733fd0a..53a01d278e6da 100644 --- a/clang/lib/Analysis/plugins/SampleAnalyzer/MainCallChecker.cpp +++ b/clang/lib/Analysis/plugins/SampleAnalyzer/MainCallChecker.cpp @@ -3,12 +3,16 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h" +// This simple plugin is used by clang/test/Analysis/checker-plugins.c +// to test the use of a checker that is defined in a plugin. + using namespace clang; using namespace ento; namespace { class MainCallChecker : public Checker> { - mutable std::unique_ptr BT; + + const BugType BT{this, "call to main", "example analyzer plugin"}; public: void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; @@ -33,21 +37,17 @@ void MainCallChecker::checkPreStmt(const CallExpr *CE, if (!N) return; - if (!BT) - BT.reset(new BugType(this, "call to main", "example analyzer plugin")); - auto report = - std::make_unique(*BT, BT->getDescription(), N); + std::make_unique(BT, BT.getDescription(), N); report->addRange(Callee->getSourceRange()); C.emitReport(std::move(report)); } } // Register plugin! -extern "C" void clang_registerCheckers(CheckerRegistry ®istry) { - registry.addChecker( - "example.MainCallChecker", "Disallows calls to functions called main", - ""); +extern "C" void clang_registerCheckers(CheckerRegistry &Registry) { + Registry.addChecker("example.MainCallChecker", + "Example Description"); } extern "C" const char clang_analyzerAPIVersionString[] = diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index 5c2af9b080b83..e3f9760ac7ce3 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -757,6 +757,9 @@ std::unique_ptr AllocateTarget(const llvm::Triple &Triple, case llvm::Triple::FreeBSD: return std::make_unique>(Triple, Opts); + case llvm::Triple::OpenBSD: + return std::make_unique>(Triple, + Opts); default: return std::make_unique(Triple, Opts); } diff --git a/clang/lib/Basic/Targets/ARM.cpp b/clang/lib/Basic/Targets/ARM.cpp index 7ff8e51f8a7f8..29de34bbc4fe4 100644 --- a/clang/lib/Basic/Targets/ARM.cpp +++ b/clang/lib/Basic/Targets/ARM.cpp @@ -623,13 +623,15 @@ bool ARMTargetInfo::handleTargetFeatures(std::vector &Features, LDREX = LDREX_W; break; case 7: + case 8: if (ArchProfile == llvm::ARM::ProfileKind::M) LDREX = LDREX_W | LDREX_H | LDREX_B; else LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; break; - case 8: case 9: + assert(ArchProfile != llvm::ARM::ProfileKind::M && + "No Armv9-M architectures defined"); LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; } diff --git a/clang/lib/Basic/Targets/Mips.h b/clang/lib/Basic/Targets/Mips.h index 35501ed44ccd7..e199df32f56ee 100644 --- a/clang/lib/Basic/Targets/Mips.h +++ b/clang/lib/Basic/Targets/Mips.h @@ -129,7 +129,7 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo { LongWidth = LongAlign = 32; MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32; PointerWidth = PointerAlign = 32; - PtrDiffType = SignedInt; + PtrDiffType = IntPtrType = SignedInt; SizeType = UnsignedInt; SuitableAlign = 64; } @@ -155,7 +155,7 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo { IntMaxType = Int64Type; LongWidth = LongAlign = 64; PointerWidth = PointerAlign = 64; - PtrDiffType = SignedLong; + PtrDiffType = IntPtrType = SignedLong; SizeType = UnsignedLong; } @@ -165,7 +165,7 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo { IntMaxType = Int64Type; LongWidth = LongAlign = 32; PointerWidth = PointerAlign = 32; - PtrDiffType = SignedInt; + PtrDiffType = IntPtrType = SignedInt; SizeType = UnsignedInt; } diff --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h index 42cff6540c5e3..94b018a0751d1 100644 --- a/clang/lib/Basic/Targets/OSTargets.h +++ b/clang/lib/Basic/Targets/OSTargets.h @@ -496,6 +496,7 @@ class LLVM_LIBRARY_VISIBILITY OpenBSDTargetInfo : public OSTargetInfo { case llvm::Triple::sparcv9: this->MCountName = "_mcount"; break; + case llvm::Triple::loongarch64: case llvm::Triple::riscv64: break; } diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h index 1abf798d93129..c13b286cd7916 100644 --- a/clang/lib/Basic/Targets/SPIR.h +++ b/clang/lib/Basic/Targets/SPIR.h @@ -264,6 +264,9 @@ class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public SPIRTargetInfo { PointerWidth = PointerAlign = 32; SizeType = TargetInfo::UnsignedInt; PtrDiffType = IntPtrType = TargetInfo::SignedInt; + // SPIR32 has support for atomic ops if atomic extension is enabled. + // Take the maximum because it's possible the Host supports wider types. + MaxAtomicInlineWidth = std::max(MaxAtomicInlineWidth, 32); resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-" "v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"); } @@ -281,6 +284,9 @@ class LLVM_LIBRARY_VISIBILITY SPIR64TargetInfo : public SPIRTargetInfo { PointerWidth = PointerAlign = 64; SizeType = TargetInfo::UnsignedLong; PtrDiffType = IntPtrType = TargetInfo::SignedLong; + // SPIR64 has support for atomic ops if atomic extension is enabled. + // Take the maximum because it's possible the Host supports wider types. + MaxAtomicInlineWidth = std::max(MaxAtomicInlineWidth, 64); resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-" "v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"); } diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h index 5bd53ebc52ab5..73c9fb924f682 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h @@ -348,22 +348,6 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { return CIRBaseBuilderTy::createStore(loc, val, dst.getPointer(), align); } - mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real, - mlir::Value imag) { - auto resultComplexTy = cir::ComplexType::get(real.getType()); - return create(loc, resultComplexTy, real, imag); - } - - mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand) { - auto operandTy = mlir::cast(operand.getType()); - return create(loc, operandTy.getElementType(), operand); - } - - mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand) { - auto operandTy = mlir::cast(operand.getType()); - return create(loc, operandTy.getElementType(), operand); - } - /// Create a cir.complex.real_ptr operation that derives a pointer to the real /// part of the complex value pointed to by the specified pointer value. mlir::Value createComplexRealPtr(mlir::Location loc, mlir::Value value) { @@ -424,21 +408,23 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { } mlir::Value createSetBitfield(mlir::Location loc, mlir::Type resultType, - mlir::Value dstAddr, mlir::Type storageType, + Address dstAddr, mlir::Type storageType, mlir::Value src, const CIRGenBitFieldInfo &info, - bool isLvalueVolatile, bool useVolatile) { - return create(loc, resultType, dstAddr, storageType, - src, info.name, info.size, info.offset, - info.isSigned, isLvalueVolatile); + bool isLvalueVolatile) { + return create( + loc, resultType, dstAddr.getPointer(), storageType, src, info.name, + info.size, info.offset, info.isSigned, isLvalueVolatile, + dstAddr.getAlignment().getAsAlign().value()); } mlir::Value createGetBitfield(mlir::Location loc, mlir::Type resultType, - mlir::Value addr, mlir::Type storageType, + Address addr, mlir::Type storageType, const CIRGenBitFieldInfo &info, - bool isLvalueVolatile, bool useVolatile) { - return create(loc, resultType, addr, storageType, - info.name, info.size, info.offset, - info.isSigned, isLvalueVolatile); + bool isLvalueVolatile) { + return create( + loc, resultType, addr.getPointer(), storageType, info.name, info.size, + info.offset, info.isSigned, isLvalueVolatile, + addr.getAlignment().getAsAlign().value()); } }; diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 72e8d71c366d8..ef136f80637f3 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -57,6 +57,20 @@ static RValue emitBuiltinBitOp(CIRGenFunction &cgf, const CallExpr *e, return RValue::get(result); } +RValue CIRGenFunction::emitRotate(const CallExpr *e, bool isRotateLeft) { + mlir::Value input = emitScalarExpr(e->getArg(0)); + mlir::Value amount = emitScalarExpr(e->getArg(1)); + + // TODO(cir): MSVC flavor bit rotate builtins use different types for input + // and amount, but cir.rotate requires them to have the same type. Cast amount + // to the type of input when necessary. + assert(!cir::MissingFeatures::msvcBuiltins()); + + auto r = builder.create(getLoc(e->getSourceRange()), input, + amount, isRotateLeft); + return RValue::get(r); +} + RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, const CallExpr *e, ReturnValueSlot returnValue) { @@ -107,11 +121,18 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, return RValue::get(nullptr); } + case Builtin::BI__builtin_assume_separate_storage: { + mlir::Value value0 = emitScalarExpr(e->getArg(0)); + mlir::Value value1 = emitScalarExpr(e->getArg(1)); + builder.create(loc, value0, value1); + return RValue::get(nullptr); + } + case Builtin::BI__builtin_complex: { mlir::Value real = emitScalarExpr(e->getArg(0)); mlir::Value imag = emitScalarExpr(e->getArg(1)); mlir::Value complex = builder.createComplexCreate(loc, real, imag); - return RValue::get(complex); + return RValue::getComplex(complex); } case Builtin::BI__builtin_creal: @@ -136,6 +157,18 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, return RValue::get(imag); } + case Builtin::BI__builtin_conj: + case Builtin::BI__builtin_conjf: + case Builtin::BI__builtin_conjl: + case Builtin::BIconj: + case Builtin::BIconjf: + case Builtin::BIconjl: { + mlir::Value complex = emitComplexExpr(e->getArg(0)); + mlir::Value conj = builder.createUnaryOp(getLoc(e->getExprLoc()), + cir::UnaryOpKind::Not, complex); + return RValue::getComplex(conj); + } + case Builtin::BI__builtin_clrsb: case Builtin::BI__builtin_clrsbl: case Builtin::BI__builtin_clrsbll: @@ -219,6 +252,18 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, mlir::Value arg = emitScalarExpr(e->getArg(0)); return RValue::get(builder.create(loc, arg)); } + + case Builtin::BI__builtin_rotateleft8: + case Builtin::BI__builtin_rotateleft16: + case Builtin::BI__builtin_rotateleft32: + case Builtin::BI__builtin_rotateleft64: + return emitRotate(e, /*isRotateLeft=*/true); + + case Builtin::BI__builtin_rotateright8: + case Builtin::BI__builtin_rotateright16: + case Builtin::BI__builtin_rotateright32: + case Builtin::BI__builtin_rotateright64: + return emitRotate(e, /*isRotateLeft=*/false); } // If this is an alias for a lib function (e.g. __builtin_sin), emit diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h index eb079b877b7ff..5929568505ef2 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h +++ b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h @@ -75,6 +75,11 @@ class CIRGenCXXABI { /// Emit dtor variants required by this ABI. virtual void emitCXXDestructors(const clang::CXXDestructorDecl *d) = 0; + virtual void emitDestructorCall(CIRGenFunction &cgf, + const CXXDestructorDecl *dd, CXXDtorType type, + bool forVirtualBase, bool delegating, + Address thisAddr, QualType thisTy) = 0; + /// Returns true if the given destructor type should be emitted as a linkonce /// delegating thunk, regardless of whether the dtor is defined in this TU or /// not. diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp index 8da832d9118e3..67d8988a5fbbd 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp @@ -246,6 +246,29 @@ static void emitNewInitializer(CIRGenFunction &cgf, const CXXNewExpr *e, } } +RValue CIRGenFunction::emitCXXDestructorCall( + GlobalDecl dtor, const CIRGenCallee &callee, mlir::Value thisVal, + QualType thisTy, mlir::Value implicitParam, QualType implicitParamTy, + const CallExpr *ce) { + const CXXMethodDecl *dtorDecl = cast(dtor.getDecl()); + + assert(!thisTy.isNull()); + assert(thisTy->getAsCXXRecordDecl() == dtorDecl->getParent() && + "Pointer/Object mixup"); + + assert(!cir::MissingFeatures::addressSpace()); + + CallArgList args; + commonBuildCXXMemberOrOperatorCall(*this, dtorDecl, thisVal, implicitParam, + implicitParamTy, ce, args, nullptr); + assert((ce || dtor.getDecl()) && "expected source location provider"); + assert(!cir::MissingFeatures::opCallMustTail()); + return emitCall(cgm.getTypes().arrangeCXXStructorDeclaration(dtor), callee, + ReturnValueSlot(), args, nullptr, + ce ? getLoc(ce->getExprLoc()) + : getLoc(dtor.getDecl()->getSourceRange())); +} + /// Emit a call to an operator new or operator delete function, as implicitly /// created by new-expressions and delete-expressions. static RValue emitNewDeleteCall(CIRGenFunction &cgf, diff --git a/clang/lib/CIR/CodeGen/CIRGenClass.cpp b/clang/lib/CIR/CodeGen/CIRGenClass.cpp index 8667bb60d114e..fbf53dbdf385b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenClass.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenClass.cpp @@ -392,6 +392,14 @@ void CIRGenFunction::emitDelegatingCXXConstructorCall( } } +void CIRGenFunction::emitCXXDestructorCall(const CXXDestructorDecl *dd, + CXXDtorType type, + bool forVirtualBase, bool delegating, + Address thisAddr, QualType thisTy) { + cgm.getCXXABI().emitDestructorCall(*this, dd, type, forVirtualBase, + delegating, thisAddr, thisTy); +} + Address CIRGenFunction::getAddressOfBaseClass( Address value, const CXXRecordDecl *derived, llvm::iterator_range path, diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 51da48d330f55..1f64801926887 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -333,13 +333,12 @@ mlir::Value CIRGenFunction::emitStoreThroughBitfieldLValue(RValue src, Address ptr = dst.getBitFieldAddress(); assert(!cir::MissingFeatures::armComputeVolatileBitfields()); - const bool useVolatile = false; mlir::Value dstAddr = dst.getAddress().getPointer(); - return builder.createSetBitfield(dstAddr.getLoc(), resLTy, dstAddr, + return builder.createSetBitfield(dstAddr.getLoc(), resLTy, ptr, ptr.getElementType(), src.getValue(), info, - dst.isVolatileQualified(), useVolatile); + dst.isVolatileQualified()); } RValue CIRGenFunction::emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc) { @@ -352,8 +351,7 @@ RValue CIRGenFunction::emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc) { assert(!cir::MissingFeatures::armComputeVolatileBitfields()); mlir::Value field = builder.createGetBitfield( - getLoc(loc), resLTy, ptr.getPointer(), ptr.getElementType(), info, - lv.isVolatile(), false); + getLoc(loc), resLTy, ptr, ptr.getElementType(), info, lv.isVolatile()); assert(!cir::MissingFeatures::opLoadEmitScalarRangeCheck() && "NYI"); return RValue::get(field); } @@ -366,7 +364,10 @@ Address CIRGenFunction::getAddrOfBitFieldStorage(LValue base, cir::PointerType fieldPtr = cir::PointerType::get(fieldType); cir::GetMemberOp sea = getBuilder().createGetMember( loc, fieldPtr, base.getPointer(), field->getName(), index); - return Address(sea, CharUnits::One()); + auto rec = cast(base.getAddress().getElementType()); + CharUnits offset = CharUnits::fromQuantity( + rec.getElementOffset(cgm.getDataLayout().layout, index)); + return Address(sea, base.getAlignment().alignmentAtOffset(offset)); } LValue CIRGenFunction::emitLValueForBitField(LValue base, @@ -662,7 +663,8 @@ LValue CIRGenFunction::emitUnaryOpLValue(const UnaryOperator *e) { } case UO_PreInc: case UO_PreDec: { - bool isInc = e->isIncrementOp(); + cir::UnaryOpKind kind = + e->isIncrementOp() ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec; LValue lv = emitLValue(e->getSubExpr()); assert(e->isPrefix() && "Prefix operator in unexpected state!"); @@ -671,7 +673,7 @@ LValue CIRGenFunction::emitUnaryOpLValue(const UnaryOperator *e) { cgm.errorNYI(e->getSourceRange(), "UnaryOp complex inc/dec"); lv = LValue(); } else { - emitScalarPrePostIncDec(e, lv, isInc, /*isPre=*/true); + emitScalarPrePostIncDec(e, lv, kind, /*isPre=*/true); } return lv; @@ -1053,6 +1055,67 @@ LValue CIRGenFunction::emitMemberExpr(const MemberExpr *e) { llvm_unreachable("Unhandled member declaration!"); } +/// Evaluate an expression into a given memory location. +void CIRGenFunction::emitAnyExprToMem(const Expr *e, Address location, + Qualifiers quals, bool isInit) { + // FIXME: This function should take an LValue as an argument. + switch (getEvaluationKind(e->getType())) { + case cir::TEK_Complex: { + LValue lv = makeAddrLValue(location, e->getType()); + emitComplexExprIntoLValue(e, lv, isInit); + return; + } + + case cir::TEK_Aggregate: { + emitAggExpr(e, AggValueSlot::forAddr(location, quals, + AggValueSlot::IsDestructed_t(isInit), + AggValueSlot::IsAliased_t(!isInit), + AggValueSlot::MayOverlap)); + return; + } + + case cir::TEK_Scalar: { + RValue rv = RValue::get(emitScalarExpr(e)); + LValue lv = makeAddrLValue(location, e->getType()); + emitStoreThroughLValue(rv, lv); + return; + } + } + + llvm_unreachable("bad evaluation kind"); +} + +LValue CIRGenFunction::emitCompoundLiteralLValue(const CompoundLiteralExpr *e) { + if (e->isFileScope()) { + cgm.errorNYI(e->getSourceRange(), "emitCompoundLiteralLValue: FileScope"); + return {}; + } + + if (e->getType()->isVariablyModifiedType()) { + cgm.errorNYI(e->getSourceRange(), + "emitCompoundLiteralLValue: VariablyModifiedType"); + return {}; + } + + Address declPtr = createMemTemp(e->getType(), getLoc(e->getSourceRange()), + ".compoundliteral"); + const Expr *initExpr = e->getInitializer(); + LValue result = makeAddrLValue(declPtr, e->getType(), AlignmentSource::Decl); + + emitAnyExprToMem(initExpr, declPtr, e->getType().getQualifiers(), + /*Init*/ true); + + // Block-scope compound literals are destroyed at the end of the enclosing + // scope in C. + if (!getLangOpts().CPlusPlus && e->getType().isDestructedType()) { + cgm.errorNYI(e->getSourceRange(), + "emitCompoundLiteralLValue: non C++ DestructedType"); + return {}; + } + + return result; +} + LValue CIRGenFunction::emitCallExprLValue(const CallExpr *e) { RValue rv = emitCallExpr(e); diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp index 3273d9000771a..6756a7ce067a5 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp @@ -52,11 +52,37 @@ class ComplexExprEmitter : public StmtVisitor { mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *e); mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e); mlir::Value VisitInitListExpr(const InitListExpr *e); + + mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) { + return emitLoadOfLValue(e); + } + mlir::Value VisitImaginaryLiteral(const ImaginaryLiteral *il); mlir::Value VisitParenExpr(ParenExpr *e); mlir::Value VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e); + + mlir::Value VisitPrePostIncDec(const UnaryOperator *e, cir::UnaryOpKind op, + bool isPre); + + mlir::Value VisitUnaryPostDec(const UnaryOperator *e) { + return VisitPrePostIncDec(e, cir::UnaryOpKind::Dec, false); + } + + mlir::Value VisitUnaryPostInc(const UnaryOperator *e) { + return VisitPrePostIncDec(e, cir::UnaryOpKind::Inc, false); + } + + mlir::Value VisitUnaryPreDec(const UnaryOperator *e) { + return VisitPrePostIncDec(e, cir::UnaryOpKind::Dec, true); + } + + mlir::Value VisitUnaryPreInc(const UnaryOperator *e) { + return VisitPrePostIncDec(e, cir::UnaryOpKind::Inc, true); + } + mlir::Value VisitUnaryDeref(const Expr *e); + mlir::Value VisitUnaryNot(const UnaryOperator *e); struct BinOpInfo { mlir::Location loc; @@ -230,8 +256,7 @@ mlir::Value ComplexExprEmitter::VisitBinComma(const BinaryOperator *e) { mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) { if (e->getCallReturnType(cgf.getContext())->isReferenceType()) return emitLoadOfLValue(e); - - return cgf.emitCallExpr(e).getValue(); + return cgf.emitCallExpr(e).getComplexValue(); } mlir::Value ComplexExprEmitter::VisitCastExpr(CastExpr *e) { @@ -334,10 +359,22 @@ mlir::Value ComplexExprEmitter::VisitSubstNonTypeTemplateParmExpr( return Visit(e->getReplacement()); } +mlir::Value ComplexExprEmitter::VisitPrePostIncDec(const UnaryOperator *e, + cir::UnaryOpKind op, + bool isPre) { + LValue lv = cgf.emitLValue(e->getSubExpr()); + return cgf.emitComplexPrePostIncDec(e, lv, op, isPre); +} + mlir::Value ComplexExprEmitter::VisitUnaryDeref(const Expr *e) { return emitLoadOfLValue(e); } +mlir::Value ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *e) { + mlir::Value op = Visit(e->getSubExpr()); + return builder.createNot(op); +} + mlir::Value ComplexExprEmitter::emitPromoted(const Expr *e, QualType promotionTy) { e = e->IgnoreParens(); @@ -417,6 +454,41 @@ mlir::Value CIRGenFunction::emitComplexExpr(const Expr *e) { return ComplexExprEmitter(*this).Visit(const_cast(e)); } +mlir::Value CIRGenFunction::emitComplexPrePostIncDec(const UnaryOperator *e, + LValue lv, + cir::UnaryOpKind op, + bool isPre) { + assert(op == cir::UnaryOpKind::Inc || + op == cir::UnaryOpKind::Dec && "Invalid UnaryOp kind for ComplexType"); + + mlir::Value inVal = emitLoadOfComplex(lv, e->getExprLoc()); + mlir::Location loc = getLoc(e->getExprLoc()); + mlir::Value incVal = builder.createUnaryOp(loc, op, inVal); + + // Store the updated result through the lvalue. + emitStoreOfComplex(loc, incVal, lv, /*isInit=*/false); + + if (getLangOpts().OpenMP) + cgm.errorNYI(loc, "emitComplexPrePostIncDec OpenMP"); + + // If this is a postinc, return the value read from memory, otherwise use the + // updated value. + return isPre ? incVal : inVal; +} + +void CIRGenFunction::emitComplexExprIntoLValue(const Expr *e, LValue dest, + bool isInit) { + assert(e && getComplexType(e->getType()) && + "Invalid complex expression to emit"); + ComplexExprEmitter emitter(*this); + mlir::Value value = emitter.Visit(const_cast(e)); + emitter.emitStoreOfComplex(getLoc(e->getExprLoc()), value, dest, isInit); +} + +mlir::Value CIRGenFunction::emitLoadOfComplex(LValue src, SourceLocation loc) { + return ComplexExprEmitter(*this).emitLoadOfLValue(src, loc); +} + void CIRGenFunction::emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest, bool isInit) { ComplexExprEmitter(*this).emitStoreOfComplex(loc, v, dest, isInit); diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 9e13b4c83e3a8..eba6bffbf2927 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -233,6 +233,10 @@ class ScalarExprEmitter : public StmtVisitor { mlir::Value VisitMemberExpr(MemberExpr *e); + mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) { + return emitLoadOfLValue(e); + } + mlir::Value VisitInitListExpr(InitListExpr *e); mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) { @@ -383,22 +387,22 @@ class ScalarExprEmitter : public StmtVisitor { // Unary Operators. mlir::Value VisitUnaryPostDec(const UnaryOperator *e) { LValue lv = cgf.emitLValue(e->getSubExpr()); - return emitScalarPrePostIncDec(e, lv, false, false); + return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Dec, false); } mlir::Value VisitUnaryPostInc(const UnaryOperator *e) { LValue lv = cgf.emitLValue(e->getSubExpr()); - return emitScalarPrePostIncDec(e, lv, true, false); + return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Inc, false); } mlir::Value VisitUnaryPreDec(const UnaryOperator *e) { LValue lv = cgf.emitLValue(e->getSubExpr()); - return emitScalarPrePostIncDec(e, lv, false, true); + return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Dec, true); } mlir::Value VisitUnaryPreInc(const UnaryOperator *e) { LValue lv = cgf.emitLValue(e->getSubExpr()); - return emitScalarPrePostIncDec(e, lv, true, true); + return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Inc, true); } mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv, - bool isInc, bool isPre) { + cir::UnaryOpKind kind, bool isPre) { if (cgf.getLangOpts().OpenMP) cgf.cgm.errorNYI(e->getSourceRange(), "inc/dec OpenMP"); @@ -427,7 +431,7 @@ class ScalarExprEmitter : public StmtVisitor { // -> bool = ((int)bool + 1 != 0) // An interesting aspect of this is that increment is always true. // Decrement does not have this property. - if (isInc && type->isBooleanType()) { + if (kind == cir::UnaryOpKind::Inc && type->isBooleanType()) { value = builder.getTrue(cgf.getLoc(e->getExprLoc())); } else if (type->isIntegerType()) { QualType promotedType; @@ -458,7 +462,7 @@ class ScalarExprEmitter : public StmtVisitor { assert(!cir::MissingFeatures::sanitizers()); if (e->canOverflow() && type->isSignedIntegerOrEnumerationType()) { - value = emitIncDecConsiderOverflowBehavior(e, value, isInc); + value = emitIncDecConsiderOverflowBehavior(e, value, kind); } else { cir::UnaryOpKind kind = e->isIncrementOp() ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec; @@ -480,7 +484,7 @@ class ScalarExprEmitter : public StmtVisitor { // For everything else, we can just do a simple increment. mlir::Location loc = cgf.getLoc(e->getSourceRange()); CIRGenBuilderTy &builder = cgf.getBuilder(); - int amount = (isInc ? 1 : -1); + int amount = kind == cir::UnaryOpKind::Inc ? 1 : -1; mlir::Value amt = builder.getSInt32(amount, loc); assert(!cir::MissingFeatures::sanitizers()); value = builder.createPtrStride(loc, value, amt); @@ -500,8 +504,8 @@ class ScalarExprEmitter : public StmtVisitor { if (mlir::isa(value.getType())) { // Create the inc/dec operation. // NOTE(CIR): clang calls CreateAdd but folds this to a unary op - cir::UnaryOpKind kind = - (isInc ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec); + assert(kind == cir::UnaryOpKind::Inc || + kind == cir::UnaryOpKind::Dec && "Invalid UnaryOp kind"); value = emitUnaryOp(e, kind, value); } else { cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec other fp type"); @@ -532,9 +536,9 @@ class ScalarExprEmitter : public StmtVisitor { mlir::Value emitIncDecConsiderOverflowBehavior(const UnaryOperator *e, mlir::Value inVal, - bool isInc) { - cir::UnaryOpKind kind = - e->isIncrementOp() ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec; + cir::UnaryOpKind kind) { + assert(kind == cir::UnaryOpKind::Inc || + kind == cir::UnaryOpKind::Dec && "Invalid UnaryOp kind"); switch (cgf.getLangOpts().getSignedOverflowBehavior()) { case LangOptions::SOB_Defined: return emitUnaryOp(e, kind, inVal, /*nsw=*/false); @@ -2147,8 +2151,9 @@ mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator( } mlir::Value CIRGenFunction::emitScalarPrePostIncDec(const UnaryOperator *e, - LValue lv, bool isInc, + LValue lv, + cir::UnaryOpKind kind, bool isPre) { return ScalarExprEmitter(*this, builder) - .emitScalarPrePostIncDec(e, lv, isInc, isPre); + .emitScalarPrePostIncDec(e, lv, kind, isPre); } diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index e532b9d855843..3e69e5673dd86 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -593,11 +593,12 @@ void CIRGenFunction::emitDestructorBody(FunctionArgList &args) { assert(!cir::MissingFeatures::dtorCleanups()); - // TODO(cir): A complete destructor is supposed to call the base destructor. - // Since we have to emit both dtor kinds we just fall through for now and. - // As long as we don't support virtual bases this should be functionally - // equivalent. - assert(!cir::MissingFeatures::completeDtors()); + if (!isTryBody) { + QualType thisTy = dtor->getFunctionObjectParameterType(); + emitCXXDestructorCall(dtor, Dtor_Base, /*forVirtualBase=*/false, + /*delegating=*/false, loadCXXThisAddress(), thisTy); + break; + } // Fallthrough: act like we're in the base variant. [[fallthrough]]; @@ -698,6 +699,8 @@ LValue CIRGenFunction::emitLValue(const Expr *e) { return emitStringLiteralLValue(cast(e)); case Expr::MemberExprClass: return emitMemberExpr(cast(e)); + case Expr::CompoundLiteralExprClass: + return emitCompoundLiteralLValue(cast(e)); case Expr::BinaryOperatorClass: return emitBinaryOperatorLValue(cast(e)); case Expr::CompoundAssignOperatorClass: { diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 1346333739bc1..2aceeef793385 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -757,6 +757,11 @@ class CIRGenFunction : public CIRGenTypeCache { RValue emitAnyExpr(const clang::Expr *e, AggValueSlot aggSlot = AggValueSlot::ignored()); + /// Emits the code necessary to evaluate an arbitrary expression into the + /// given memory location. + void emitAnyExprToMem(const Expr *e, Address location, Qualifiers quals, + bool isInitializer); + /// Similarly to emitAnyExpr(), however, the result will always be accessible /// even if no aggregate location is provided. RValue emitAnyExprToTemp(const clang::Expr *e); @@ -828,6 +833,7 @@ class CIRGenFunction : public CIRGenTypeCache { mlir::Value emitCheckedArgForAssume(const Expr *e); LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e); + LValue emitCompoundLiteralLValue(const CompoundLiteralExpr *e); void emitConstructorBody(FunctionArgList &args); void emitDestructorBody(FunctionArgList &args); @@ -847,6 +853,15 @@ class CIRGenFunction : public CIRGenTypeCache { bool delegating, Address thisAddr, CallArgList &args, clang::SourceLocation loc); + void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type, + bool forVirtualBase, bool delegating, + Address thisAddr, QualType thisTy); + + RValue emitCXXDestructorCall(GlobalDecl dtor, const CIRGenCallee &callee, + mlir::Value thisVal, QualType thisTy, + mlir::Value implicitParam, + QualType implicitParamTy, const CallExpr *e); + mlir::LogicalResult emitCXXForRangeStmt(const CXXForRangeStmt &s, llvm::ArrayRef attrs); @@ -911,7 +926,7 @@ class CIRGenFunction : public CIRGenTypeCache { mlir::Value emitScalarExpr(const clang::Expr *e); mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv, - bool isInc, bool isPre); + cir::UnaryOpKind kind, bool isPre); /// Build a debug stoppoint if we are emitting debug info. void emitStopPoint(const Stmt *s); @@ -930,6 +945,11 @@ class CIRGenFunction : public CIRGenTypeCache { /// returning the result. mlir::Value emitComplexExpr(const Expr *e); + void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit); + + mlir::Value emitComplexPrePostIncDec(const UnaryOperator *e, LValue lv, + cir::UnaryOpKind op, bool isPre); + LValue emitComplexAssignmentLValue(const BinaryOperator *e); void emitCompoundStmt(const clang::CompoundStmt &s); @@ -980,6 +1000,9 @@ class CIRGenFunction : public CIRGenTypeCache { RValue emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc); + /// Load a complex number from the specified l-value. + mlir::Value emitLoadOfComplex(LValue src, SourceLocation loc); + /// Given an expression that represents a value lvalue, this method emits /// the address of the lvalue, then loads the result as an rvalue, /// returning the rvalue. @@ -1030,6 +1053,8 @@ class CIRGenFunction : public CIRGenTypeCache { mlir::LogicalResult emitReturnStmt(const clang::ReturnStmt &s); + RValue emitRotate(const CallExpr *e, bool isRotateLeft); + mlir::Value emitScalarConstant(const ConstantEmission &constant, Expr *e); /// Emit a conversion from the specified type to the specified destination diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp index 1496d877e7239..6577f5fb0f2ef 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -46,6 +46,11 @@ class CIRGenItaniumCXXABI : public CIRGenCXXABI { void emitCXXDestructors(const clang::CXXDestructorDecl *d) override; void emitCXXStructor(clang::GlobalDecl gd) override; + void emitDestructorCall(CIRGenFunction &cgf, const CXXDestructorDecl *dd, + CXXDtorType type, bool forVirtualBase, + bool delegating, Address thisAddr, + QualType thisTy) override; + bool useThunkForDtorVariant(const CXXDestructorDecl *dtor, CXXDtorType dt) const override { // Itanium does not emit any destructor variant as an inline thunk. @@ -240,6 +245,25 @@ bool CIRGenItaniumCXXABI::needsVTTParameter(GlobalDecl gd) { return false; } +void CIRGenItaniumCXXABI::emitDestructorCall( + CIRGenFunction &cgf, const CXXDestructorDecl *dd, CXXDtorType type, + bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy) { + GlobalDecl gd(dd, type); + if (needsVTTParameter(gd)) { + cgm.errorNYI(dd->getSourceRange(), "emitDestructorCall: VTT"); + } + + mlir::Value vtt = nullptr; + ASTContext &astContext = cgm.getASTContext(); + QualType vttTy = astContext.getPointerType(astContext.VoidPtrTy); + assert(!cir::MissingFeatures::appleKext()); + CIRGenCallee callee = + CIRGenCallee::forDirect(cgm.getAddrOfCXXStructor(gd), gd); + + cgf.emitCXXDestructorCall(gd, callee, thisAddr.getPointer(), thisTy, vtt, + vttTy, nullptr); +} + CIRGenCXXABI *clang::CIRGen::CreateCIRGenItaniumCXXABI(CIRGenModule &cgm) { switch (cgm.getASTContext().getCXXABIKind()) { case TargetCXXABI::GenericItanium: diff --git a/clang/lib/CIR/CodeGen/CIRGenValue.h b/clang/lib/CIR/CodeGen/CIRGenValue.h index 0a6dba5e80a62..0832c4141a10f 100644 --- a/clang/lib/CIR/CodeGen/CIRGenValue.h +++ b/clang/lib/CIR/CodeGen/CIRGenValue.h @@ -58,6 +58,12 @@ class RValue { return value; } + /// Return the value of this complex value. + mlir::Value getComplexValue() const { + assert(isComplex() && "Not a complex!"); + return value; + } + /// Return the value of the address of the aggregate. Address getAggregateAddress() const { assert(isAggregate() && "Not an aggregate!"); diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp index 5493b86a0a321..8f848c7345610 100644 --- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp @@ -8,7 +8,9 @@ #include "PassDetail.h" #include "clang/AST/ASTContext.h" +#include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" +#include "clang/CIR/Dialect/IR/CIROpsEnums.h" #include "clang/CIR/Dialect/Passes.h" #include @@ -21,17 +23,70 @@ struct LoweringPreparePass : public LoweringPrepareBase { LoweringPreparePass() = default; void runOnOperation() override; - void runOnOp(Operation *op); + void runOnOp(mlir::Operation *op); + void lowerUnaryOp(cir::UnaryOp op); }; } // namespace -void LoweringPreparePass::runOnOp(Operation *op) {} +void LoweringPreparePass::lowerUnaryOp(cir::UnaryOp op) { + mlir::Type ty = op.getType(); + if (!mlir::isa(ty)) + return; + + mlir::Location loc = op.getLoc(); + cir::UnaryOpKind opKind = op.getKind(); + + CIRBaseBuilderTy builder(getContext()); + builder.setInsertionPointAfter(op); + + mlir::Value operand = op.getInput(); + mlir::Value operandReal = builder.createComplexReal(loc, operand); + mlir::Value operandImag = builder.createComplexImag(loc, operand); + + mlir::Value resultReal; + mlir::Value resultImag; + + switch (opKind) { + case cir::UnaryOpKind::Inc: + case cir::UnaryOpKind::Dec: + resultReal = builder.createUnaryOp(loc, opKind, operandReal); + resultImag = operandImag; + break; + + case cir::UnaryOpKind::Plus: + case cir::UnaryOpKind::Minus: + llvm_unreachable("Complex unary Plus/Minus NYI"); + break; + + case cir::UnaryOpKind::Not: + resultReal = operandReal; + resultImag = + builder.createUnaryOp(loc, cir::UnaryOpKind::Minus, operandImag); + break; + } + + mlir::Value result = builder.createComplexCreate(loc, resultReal, resultImag); + op.replaceAllUsesWith(result); + op.erase(); +} + +void LoweringPreparePass::runOnOp(mlir::Operation *op) { + if (auto unary = dyn_cast(op)) + lowerUnaryOp(unary); +} void LoweringPreparePass::runOnOperation() { - llvm::SmallVector opsToTransform; + mlir::Operation *op = getOperation(); + + llvm::SmallVector opsToTransform; + + op->walk([&](mlir::Operation *op) { + if (mlir::isa(op)) + opsToTransform.push_back(op); + }); - for (auto *o : opsToTransform) + for (mlir::Operation *o : opsToTransform) runOnOp(o); } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 7dcea0c8eb529..3cd7de0a56bc3 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -460,6 +460,17 @@ mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite( return mlir::success(); } +mlir::LogicalResult CIRToLLVMAssumeSepStorageOpLowering::matchAndRewrite( + cir::AssumeSepStorageOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + auto cond = rewriter.create(op.getLoc(), + rewriter.getI1Type(), 1); + rewriter.replaceOpWithNewOp( + op, cond, mlir::LLVM::AssumeSeparateStorageTag{}, adaptor.getPtr1(), + adaptor.getPtr2()); + return mlir::success(); +} + mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite( cir::BitClrsbOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { @@ -872,6 +883,21 @@ mlir::LogicalResult CIRToLLVMReturnOpLowering::matchAndRewrite( return mlir::LogicalResult::success(); } +mlir::LogicalResult CIRToLLVMRotateOpLowering::matchAndRewrite( + cir::RotateOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + // Note that LLVM intrinsic calls to @llvm.fsh{r,l}.i* have the same type as + // the operand. + mlir::Value input = adaptor.getInput(); + if (op.isRotateLeft()) + rewriter.replaceOpWithNewOp(op, input, input, + adaptor.getAmount()); + else + rewriter.replaceOpWithNewOp(op, input, input, + adaptor.getAmount()); + return mlir::LogicalResult::success(); +} + static mlir::LogicalResult rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands, mlir::ConversionPatternRewriter &rewriter, @@ -2051,6 +2077,7 @@ void ConvertCIRToLLVMPass::runOnOperation() { patterns.add< // clang-format off CIRToLLVMAssumeOpLowering, + CIRToLLVMAssumeSepStorageOpLowering, CIRToLLVMBaseClassAddrOpLowering, CIRToLLVMBinOpLowering, CIRToLLVMBitClrsbOpLowering, @@ -2077,6 +2104,7 @@ void ConvertCIRToLLVMPass::runOnOperation() { CIRToLLVMGetBitfieldOpLowering, CIRToLLVMGetGlobalOpLowering, CIRToLLVMGetMemberOpLowering, + CIRToLLVMRotateOpLowering, CIRToLLVMSelectOpLowering, CIRToLLVMSetBitfieldOpLowering, CIRToLLVMShiftOpLowering, @@ -2555,7 +2583,7 @@ mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite( assert(storageSize > size && "Invalid bitfield size."); mlir::Value val = rewriter.create( - op.getLoc(), intType, adaptor.getAddr(), /* alignment */ 0, + op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(), op.getIsVolatile()); srcVal = @@ -2572,7 +2600,7 @@ mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite( } rewriter.create(op.getLoc(), srcVal, adaptor.getAddr(), - /* alignment */ 0, op.getIsVolatile()); + op.getAlignment(), op.getIsVolatile()); mlir::Type resultTy = getTypeConverter()->convertType(op.getType()); @@ -2646,7 +2674,8 @@ mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite( computeBitfieldIntType(storageType, context, storageSize); mlir::Value val = rewriter.create( - op.getLoc(), intType, adaptor.getAddr(), 0, op.getIsVolatile()); + op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(), + op.getIsVolatile()); val = rewriter.create(op.getLoc(), intType, val); if (info.getIsSigned()) { diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h index 3c30b1bc5b072..2911ced66e58e 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h @@ -44,6 +44,16 @@ class CIRToLLVMAssumeOpLowering mlir::ConversionPatternRewriter &) const override; }; +class CIRToLLVMAssumeSepStorageOpLowering + : public mlir::OpConversionPattern { +public: + using mlir::OpConversionPattern::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(cir::AssumeSepStorageOp op, OpAdaptor, + mlir::ConversionPatternRewriter &) const override; +}; + class CIRToLLVMBitClrsbOpLowering : public mlir::OpConversionPattern { public: @@ -160,6 +170,16 @@ class CIRToLLVMReturnOpLowering mlir::ConversionPatternRewriter &) const override; }; +class CIRToLLVMRotateOpLowering + : public mlir::OpConversionPattern { +public: + using mlir::OpConversionPattern::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(cir::RotateOp op, OpAdaptor, + mlir::ConversionPatternRewriter &) const override; +}; + class CIRToLLVMCallOpLowering : public mlir::OpConversionPattern { public: using mlir::OpConversionPattern::OpConversionPattern; diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 2f6d4c414e737..1b7257857dd3b 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -407,13 +407,13 @@ static bool initTargetOptions(const CompilerInstance &CI, // Set EABI version. Options.EABIVersion = TargetOpts.EABIVersion; - if (LangOpts.hasSjLjExceptions()) + if (CodeGenOpts.hasSjLjExceptions()) Options.ExceptionModel = llvm::ExceptionHandling::SjLj; - if (LangOpts.hasSEHExceptions()) + if (CodeGenOpts.hasSEHExceptions()) Options.ExceptionModel = llvm::ExceptionHandling::WinEH; - if (LangOpts.hasDWARFExceptions()) + if (CodeGenOpts.hasDWARFExceptions()) Options.ExceptionModel = llvm::ExceptionHandling::DwarfCFI; - if (LangOpts.hasWasmExceptions()) + if (CodeGenOpts.hasWasmExceptions()) Options.ExceptionModel = llvm::ExceptionHandling::Wasm; Options.NoInfsFPMath = LangOpts.NoHonorInfs; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 5f2eb76e7bacb..3f784fc8e798f 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -4108,6 +4108,22 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, return RValue::get(Result); } + case Builtin::BI__builtin_elementwise_maximumnum: { + Value *Op0 = EmitScalarExpr(E->getArg(0)); + Value *Op1 = EmitScalarExpr(E->getArg(1)); + Value *Result = Builder.CreateBinaryIntrinsic( + Intrinsic::maximumnum, Op0, Op1, nullptr, "elt.maximumnum"); + return RValue::get(Result); + } + + case Builtin::BI__builtin_elementwise_minimumnum: { + Value *Op0 = EmitScalarExpr(E->getArg(0)); + Value *Op1 = EmitScalarExpr(E->getArg(1)); + Value *Result = Builder.CreateBinaryIntrinsic( + Intrinsic::minimumnum, Op0, Op1, nullptr, "elt.minimumnum"); + return RValue::get(Result); + } + case Builtin::BI__builtin_reduce_max: { auto GetIntrinsicID = [this](QualType QT) { if (auto *VecTy = QT->getAs()) diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index c8c3d6b20c496..0bceecec6e555 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -214,7 +214,7 @@ static void appendParameterTypes( for (unsigned I = 0, E = FPT->getNumParams(); I != E; ++I) { prefix.push_back(FPT->getParamType(I)); if (ExtInfos[I].hasPassObjectSize()) - prefix.push_back(CGT.getContext().getSizeType()); + prefix.push_back(CGT.getContext().getCanonicalSizeType()); } addExtParameterInfosForCall(paramInfos, FPT.getTypePtr(), PrefixSize, @@ -2852,8 +2852,21 @@ void CodeGenModule::ConstructAttributeList(StringRef Name, if (AI.getInReg()) Attrs.addAttribute(llvm::Attribute::InReg); - if (AI.getIndirectByVal()) + // Depending on the ABI, this may be either a byval or a dead_on_return + // argument. + if (AI.getIndirectByVal()) { Attrs.addByValAttr(getTypes().ConvertTypeForMem(ParamType)); + } else { + // Add dead_on_return when the object's lifetime ends in the callee. + // This includes trivially-destructible objects, as well as objects + // whose destruction / clean-up is carried out within the callee (e.g., + // Obj-C ARC-managed structs, MSVC callee-destroyed objects). + if (!ParamType.isDestructedType() || !ParamType->isRecordType() || + ParamType->castAs() + ->getDecl() + ->isParamDestroyedInCallee()) + Attrs.addAttribute(llvm::Attribute::DeadOnReturn); + } auto *Decl = ParamType->getAsRecordDecl(); if (CodeGenOpts.PassByValueIsNoAlias && Decl && diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp index 117ef3d16e21b..5ee908922b5a3 100644 --- a/clang/lib/CodeGen/CGCoroutine.cpp +++ b/clang/lib/CodeGen/CGCoroutine.cpp @@ -1006,15 +1006,15 @@ RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E, } case llvm::Intrinsic::coro_size: { auto &Context = getContext(); - CanQualType SizeTy = Context.getSizeType(); - llvm::IntegerType *T = Builder.getIntNTy(Context.getTypeSize(SizeTy)); + llvm::IntegerType *T = + Builder.getIntNTy(Context.getTypeSize(Context.getSizeType())); llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::coro_size, T); return RValue::get(Builder.CreateCall(F)); } case llvm::Intrinsic::coro_align: { auto &Context = getContext(); - CanQualType SizeTy = Context.getSizeType(); - llvm::IntegerType *T = Builder.getIntNTy(Context.getTypeSize(SizeTy)); + llvm::IntegerType *T = + Builder.getIntNTy(Context.getTypeSize(Context.getSizeType())); llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::coro_align, T); return RValue::get(Builder.CreateCall(F)); } diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index b985db7a9494b..a371b6755f74d 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -58,13 +58,6 @@ using namespace clang; using namespace clang::CodeGen; -// TODO: consider deprecating ClArrayBoundsPseudoFn; functionality is subsumed -// by -fsanitize-annotate-debug-info -static llvm::cl::opt ClArrayBoundsPseudoFn( - "array-bounds-pseudofn", llvm::cl::Hidden, llvm::cl::Optional, - llvm::cl::desc("Emit debug info that places array-bounds instrumentation " - "in an inline function called __ubsan_check_array_bounds.")); - static uint32_t getTypeAlignIfRequired(const Type *Ty, const ASTContext &Ctx) { auto TI = Ctx.getTypeInfo(Ty); if (TI.isAlignRequired()) @@ -170,6 +163,10 @@ void CGDebugInfo::addInstToSpecificSourceAtom(llvm::Instruction *KeyInstruction, if (!Group || !CGM.getCodeGenOpts().DebugKeyInstructions) return; + llvm::DISubprogram *SP = KeyInstruction->getFunction()->getSubprogram(); + if (!SP || !SP->getKeyInstructionsEnabled()) + return; + addInstSourceAtomMetadata(KeyInstruction, Group, /*Rank=*/1); llvm::Instruction *BackupI = @@ -4048,7 +4045,8 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { return CreateType(cast(Ty), Unit); case Type::HLSLInlineSpirv: return CreateType(cast(Ty), Unit); - + case Type::PredefinedSugar: + return getOrCreateType(cast(Ty)->desugar(), Unit); case Type::CountAttributed: case Type::Auto: case Type::Attributed: @@ -6064,11 +6062,10 @@ void CGDebugInfo::EmitPseudoVariable(CGBuilderTy &Builder, // ptr, in this case its debug info may not match the actual type of object // being used as in the next instruction, so we will need to emit a pseudo // variable for type-casted value. - auto DeclareTypeMatches = [&](auto *DbgDeclare) { + auto DeclareTypeMatches = [&](llvm::DbgVariableRecord *DbgDeclare) { return DbgDeclare->getVariable()->getType() == Type; }; - if (any_of(llvm::findDbgDeclares(Var), DeclareTypeMatches) || - any_of(llvm::findDVRDeclares(Var), DeclareTypeMatches)) + if (any_of(llvm::findDVRDeclares(Var), DeclareTypeMatches)) return; } @@ -6476,24 +6473,25 @@ SanitizerOrdinalToCheckLabel(SanitizerKind::SanitizerOrdinal Ordinal) { llvm::DILocation *CodeGenFunction::SanitizerAnnotateDebugInfo( ArrayRef Ordinals, SanitizerHandler Handler) { + llvm::DILocation *CheckDebugLoc = Builder.getCurrentDebugLocation(); + auto *DI = getDebugInfo(); + if (!DI || !CheckDebugLoc) + return CheckDebugLoc; + const auto &AnnotateDebugInfo = + CGM.getCodeGenOpts().SanitizeAnnotateDebugInfo; + if (AnnotateDebugInfo.empty()) + return CheckDebugLoc; + std::string Label; if (Ordinals.size() == 1) Label = SanitizerOrdinalToCheckLabel(Ordinals[0]); else Label = SanitizerHandlerToCheckLabel(Handler); - llvm::DILocation *CheckDI = Builder.getCurrentDebugLocation(); - - for (auto Ord : Ordinals) { - // TODO: deprecate ClArrayBoundsPseudoFn - if (((ClArrayBoundsPseudoFn && Ord == SanitizerKind::SO_ArrayBounds) || - CGM.getCodeGenOpts().SanitizeAnnotateDebugInfo.has(Ord)) && - CheckDI) { - return getDebugInfo()->CreateSyntheticInlineAt(CheckDI, Label); - } - } + if (any_of(Ordinals, [&](auto Ord) { return AnnotateDebugInfo.has(Ord); })) + return DI->CreateSyntheticInlineAt(CheckDebugLoc, Label); - return CheckDI; + return CheckDebugLoc; } SanitizerDebugLocation::SanitizerDebugLocation( diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index ad138b9876e8c..f86af4581c345 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -131,20 +131,21 @@ const EHPersonality EHPersonality::ZOS_CPlusPlus = {"__zos_cxx_personality_v2", nullptr}; static const EHPersonality &getCPersonality(const TargetInfo &Target, - const LangOptions &L) { + const CodeGenOptions &CGOpts) { const llvm::Triple &T = Target.getTriple(); if (T.isWindowsMSVCEnvironment()) return EHPersonality::MSVC_CxxFrameHandler3; - if (L.hasSjLjExceptions()) + if (CGOpts.hasSjLjExceptions()) return EHPersonality::GNU_C_SJLJ; - if (L.hasDWARFExceptions()) + if (CGOpts.hasDWARFExceptions()) return EHPersonality::GNU_C; - if (L.hasSEHExceptions()) + if (CGOpts.hasSEHExceptions()) return EHPersonality::GNU_C_SEH; return EHPersonality::GNU_C; } static const EHPersonality &getObjCPersonality(const TargetInfo &Target, + const CodeGenOptions &CGOpts, const LangOptions &L) { const llvm::Triple &T = Target.getTriple(); if (T.isWindowsMSVCEnvironment()) @@ -152,7 +153,7 @@ static const EHPersonality &getObjCPersonality(const TargetInfo &Target, switch (L.ObjCRuntime.getKind()) { case ObjCRuntime::FragileMacOSX: - return getCPersonality(Target, L); + return getCPersonality(Target, CGOpts); case ObjCRuntime::MacOSX: case ObjCRuntime::iOS: case ObjCRuntime::WatchOS: @@ -165,9 +166,9 @@ static const EHPersonality &getObjCPersonality(const TargetInfo &Target, [[fallthrough]]; case ObjCRuntime::GCC: case ObjCRuntime::ObjFW: - if (L.hasSjLjExceptions()) + if (CGOpts.hasSjLjExceptions()) return EHPersonality::GNU_ObjC_SJLJ; - if (L.hasSEHExceptions()) + if (CGOpts.hasSEHExceptions()) return EHPersonality::GNU_ObjC_SEH; return EHPersonality::GNU_ObjC; } @@ -175,19 +176,19 @@ static const EHPersonality &getObjCPersonality(const TargetInfo &Target, } static const EHPersonality &getCXXPersonality(const TargetInfo &Target, - const LangOptions &L) { + const CodeGenOptions &CGOpts) { const llvm::Triple &T = Target.getTriple(); if (T.isWindowsMSVCEnvironment()) return EHPersonality::MSVC_CxxFrameHandler3; if (T.isOSAIX()) return EHPersonality::XL_CPlusPlus; - if (L.hasSjLjExceptions()) + if (CGOpts.hasSjLjExceptions()) return EHPersonality::GNU_CPlusPlus_SJLJ; - if (L.hasDWARFExceptions()) + if (CGOpts.hasDWARFExceptions()) return EHPersonality::GNU_CPlusPlus; - if (L.hasSEHExceptions()) + if (CGOpts.hasSEHExceptions()) return EHPersonality::GNU_CPlusPlus_SEH; - if (L.hasWasmExceptions()) + if (CGOpts.hasWasmExceptions()) return EHPersonality::GNU_Wasm_CPlusPlus; if (T.isOSzOS()) return EHPersonality::ZOS_CPlusPlus; @@ -197,6 +198,7 @@ static const EHPersonality &getCXXPersonality(const TargetInfo &Target, /// Determines the personality function to use when both C++ /// and Objective-C exceptions are being caught. static const EHPersonality &getObjCXXPersonality(const TargetInfo &Target, + const CodeGenOptions &CGOpts, const LangOptions &L) { if (Target.getTriple().isWindowsMSVCEnvironment()) return EHPersonality::MSVC_CxxFrameHandler3; @@ -205,7 +207,7 @@ static const EHPersonality &getObjCXXPersonality(const TargetInfo &Target, // In the fragile ABI, just use C++ exception handling and hope // they're not doing crazy exception mixing. case ObjCRuntime::FragileMacOSX: - return getCXXPersonality(Target, L); + return getCXXPersonality(Target, CGOpts); // The ObjC personality defers to the C++ personality for non-ObjC // handlers. Unlike the C++ case, we use the same personality @@ -213,7 +215,7 @@ static const EHPersonality &getObjCXXPersonality(const TargetInfo &Target, case ObjCRuntime::MacOSX: case ObjCRuntime::iOS: case ObjCRuntime::WatchOS: - return getObjCPersonality(Target, L); + return getObjCPersonality(Target, CGOpts, L); case ObjCRuntime::GNUstep: return Target.getTriple().isOSCygMing() ? EHPersonality::GNU_CPlusPlus_SEH @@ -223,7 +225,7 @@ static const EHPersonality &getObjCXXPersonality(const TargetInfo &Target, // mixed EH. Use the ObjC personality just to avoid returning null. case ObjCRuntime::GCC: case ObjCRuntime::ObjFW: - return getObjCPersonality(Target, L); + return getObjCPersonality(Target, CGOpts, L); } llvm_unreachable("bad runtime kind"); } @@ -237,6 +239,7 @@ static const EHPersonality &getSEHPersonalityMSVC(const llvm::Triple &T) { const EHPersonality &EHPersonality::get(CodeGenModule &CGM, const FunctionDecl *FD) { const llvm::Triple &T = CGM.getTarget().getTriple(); + const CodeGenOptions &CGOpts = CGM.getCodeGenOpts(); const LangOptions &L = CGM.getLangOpts(); const TargetInfo &Target = CGM.getTarget(); @@ -245,10 +248,10 @@ const EHPersonality &EHPersonality::get(CodeGenModule &CGM, return getSEHPersonalityMSVC(T); if (L.ObjC) - return L.CPlusPlus ? getObjCXXPersonality(Target, L) - : getObjCPersonality(Target, L); - return L.CPlusPlus ? getCXXPersonality(Target, L) - : getCPersonality(Target, L); + return L.CPlusPlus ? getObjCXXPersonality(Target, CGOpts, L) + : getObjCPersonality(Target, CGOpts, L); + return L.CPlusPlus ? getCXXPersonality(Target, CGOpts) + : getCPersonality(Target, CGOpts); } const EHPersonality &EHPersonality::get(CodeGenFunction &CGF) { @@ -344,7 +347,7 @@ void CodeGenModule::SimplifyPersonality() { return; const EHPersonality &ObjCXX = EHPersonality::get(*this, /*FD=*/nullptr); - const EHPersonality &CXX = getCXXPersonality(getTarget(), LangOpts); + const EHPersonality &CXX = getCXXPersonality(getTarget(), CodeGenOpts); if (&ObjCXX == &CXX) return; @@ -500,7 +503,7 @@ void CodeGenFunction::EmitStartEHSpec(const Decl *D) { // In Wasm EH we currently treat 'throw()' in the same way as 'noexcept'. In // case of throw with types, we ignore it and print a warning for now. // TODO Correctly handle exception specification in Wasm EH - if (CGM.getLangOpts().hasWasmExceptions()) { + if (CGM.getCodeGenOpts().hasWasmExceptions()) { if (EST == EST_DynamicNone) EHStack.pushTerminate(); else @@ -515,8 +518,8 @@ void CodeGenFunction::EmitStartEHSpec(const Decl *D) { // throw with types. // TODO Correctly handle exception specification in Emscripten EH if (getTarget().getCXXABI() == TargetCXXABI::WebAssembly && - CGM.getLangOpts().getExceptionHandling() == - LangOptions::ExceptionHandlingKind::None && + CGM.getCodeGenOpts().getExceptionHandling() == + CodeGenOptions::ExceptionHandlingKind::None && EST == EST_Dynamic) CGM.getDiags().Report(D->getLocation(), diag::warn_wasm_dynamic_exception_spec_ignored) @@ -604,7 +607,7 @@ void CodeGenFunction::EmitEndEHSpec(const Decl *D) { // In wasm we currently treat 'throw()' in the same way as 'noexcept'. In // case of throw with types, we ignore it and print a warning for now. // TODO Correctly handle exception specification in wasm - if (CGM.getLangOpts().hasWasmExceptions()) { + if (CGM.getCodeGenOpts().hasWasmExceptions()) { if (EST == EST_DynamicNone) EHStack.popTerminate(); return; diff --git a/clang/lib/CodeGen/CGLoopInfo.cpp b/clang/lib/CodeGen/CGLoopInfo.cpp index 4a9092842858b..b2b569a43038c 100644 --- a/clang/lib/CodeGen/CGLoopInfo.cpp +++ b/clang/lib/CodeGen/CGLoopInfo.cpp @@ -221,18 +221,6 @@ LoopInfo::createLoopVectorizeMetadata(const LoopAttributes &Attrs, return createUnrollAndJamMetadata(Attrs, LoopProperties, HasUserTransforms); } - // Apply all loop properties to the vectorized loop. - SmallVector FollowupLoopProperties; - FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end()); - - // Don't vectorize an already vectorized loop. - FollowupLoopProperties.push_back( - MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized"))); - - bool FollowupHasTransforms = false; - SmallVector Followup = createUnrollAndJamMetadata( - Attrs, FollowupLoopProperties, FollowupHasTransforms); - SmallVector Args; Args.append(LoopProperties.begin(), LoopProperties.end()); @@ -286,22 +274,46 @@ LoopInfo::createLoopVectorizeMetadata(const LoopAttributes &Attrs, // 5) it is implied when vectorize.width is unset (0) and the user // explicitly requested fixed-width vectorization, i.e. // vectorize.scalable.enable is false. + bool VectorizeEnabled = false; if (Attrs.VectorizeEnable != LoopAttributes::Unspecified || (IsVectorPredicateEnabled && Attrs.VectorizeWidth != 1) || Attrs.VectorizeWidth > 1 || Attrs.VectorizeScalable == LoopAttributes::Enable || (Attrs.VectorizeScalable == LoopAttributes::Disable && Attrs.VectorizeWidth != 1)) { - bool AttrVal = Attrs.VectorizeEnable != LoopAttributes::Disable; + VectorizeEnabled = Attrs.VectorizeEnable != LoopAttributes::Disable; Args.push_back( MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"), ConstantAsMetadata::get(ConstantInt::get( - llvm::Type::getInt1Ty(Ctx), AttrVal))})); + llvm::Type::getInt1Ty(Ctx), VectorizeEnabled))})); } - if (FollowupHasTransforms) - Args.push_back( - createFollowupMetadata("llvm.loop.vectorize.followup_all", Followup)); + // Apply all loop properties to the vectorized loop. + SmallVector FollowupLoopProperties; + + // If vectorization is not explicitly enabled, the follow-up metadata will be + // directly appended to the list currently being created. In that case, adding + // LoopProperties to FollowupLoopProperties would result in duplication. + if (VectorizeEnabled) + FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end()); + + // Don't vectorize an already vectorized loop. + FollowupLoopProperties.push_back( + MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized"))); + + bool FollowupHasTransforms = false; + SmallVector Followup = createUnrollAndJamMetadata( + Attrs, FollowupLoopProperties, FollowupHasTransforms); + + if (FollowupHasTransforms) { + // If vectorization is explicitly enabled, we create a follow-up metadata, + // otherwise directly add the contents of it to Args. + if (VectorizeEnabled) + Args.push_back( + createFollowupMetadata("llvm.loop.vectorize.followup_all", Followup)); + else + Args.append(Followup.begin(), Followup.end()); + } HasUserTransforms = true; return Args; diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 8e71a576552d3..8c66176942cb5 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -285,7 +285,7 @@ class ObjCCommonTypesHelper { SmallVector Params; Params.push_back(Ctx.VoidPtrTy); Params.push_back(Ctx.VoidPtrTy); - Params.push_back(Ctx.getSizeType()); + Params.push_back(Ctx.getCanonicalSizeType()); Params.push_back(Ctx.BoolTy); Params.push_back(Ctx.BoolTy); llvm::FunctionType *FTy = Types.GetFunctionType( diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index e0650067b9547..1a8c6f015bda1 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -846,11 +846,13 @@ void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) { if (HaveInsertPoint()) EmitStopPoint(&S); + ApplyAtomGroup Grp(getDebugInfo()); EmitBranchThroughCleanup(getJumpDestForLabel(S.getLabel())); } void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) { + ApplyAtomGroup Grp(getDebugInfo()); if (const LabelDecl *Target = S.getConstantTarget()) { EmitBranchThroughCleanup(getJumpDestForLabel(Target)); return; @@ -869,6 +871,8 @@ void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) { cast(IndGotoBB->begin())->addIncoming(V, CurBB); EmitBranch(IndGotoBB); + if (CurBB && CurBB->getTerminator()) + addInstToCurrentSourceAtom(CurBB->getTerminator(), nullptr); } void CodeGenFunction::EmitIfStmt(const IfStmt &S) { @@ -2672,6 +2676,9 @@ static void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect, llvm::ConstantAsMetadata::get(Loc))); } + // Make inline-asm calls Key for the debug info feature Key Instructions. + CGF.addInstToNewSourceAtom(&Result, nullptr); + if (!NoConvergent && CGF.getLangOpts().assumeFunctionsAreConvergent()) // Conservatively, mark all inline asm blocks in CUDA or OpenCL as // convergent (meaning, they may call an intrinsically convergent op, such @@ -2750,6 +2757,7 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S, } } + ApplyAtomGroup Grp(CGF.getDebugInfo()); LValue Dest = ResultRegDests[i]; // ResultTypeRequiresCast elements correspond to the first // ResultTypeRequiresCast.size() elements of RegResults. @@ -2757,7 +2765,8 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S, unsigned Size = CGF.getContext().getTypeSize(ResultRegQualTys[i]); Address A = Dest.getAddress().withElementType(ResultRegTypes[i]); if (CGF.getTargetHooks().isScalarizableAsmOperand(CGF, TruncTy)) { - Builder.CreateStore(Tmp, A); + llvm::StoreInst *S = Builder.CreateStore(Tmp, A); + CGF.addInstToCurrentSourceAtom(S, S->getValueOperand()); continue; } diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 776a646ceb32f..ab345a598c4e8 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -161,8 +161,7 @@ void CodeGenFunction::CGFPOptionsRAII::ConstructorHelper(FPOptions FPFeatures) { llvm::RoundingMode NewRoundingBehavior = FPFeatures.getRoundingMode(); CGF.Builder.setDefaultConstrainedRounding(NewRoundingBehavior); auto NewExceptionBehavior = - ToConstrainedExceptMD(static_cast( - FPFeatures.getExceptionMode())); + ToConstrainedExceptMD(FPFeatures.getExceptionMode()); CGF.Builder.setDefaultConstrainedExcept(NewExceptionBehavior); CGF.SetFastMathFlags(FPFeatures); @@ -721,7 +720,7 @@ static bool matchesStlAllocatorFn(const Decl *D, const ASTContext &Ctx) { (MD->getNumParams() != 1 && MD->getNumParams() != 2)) return false; - if (MD->parameters()[0]->getType().getCanonicalType() != Ctx.getSizeType()) + if (!Ctx.hasSameType(MD->parameters()[0]->getType(), Ctx.getSizeType())) return false; if (MD->getNumParams() == 2) { @@ -2492,6 +2491,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) { case Type::ObjCObjectPointer: case Type::BitInt: case Type::HLSLInlineSpirv: + case Type::PredefinedSugar: llvm_unreachable("type class is never variably-modified!"); case Type::Elaborated: diff --git a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp index dcfdea648e93c..7dccf82b1a7a3 100644 --- a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp @@ -416,11 +416,13 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, case AMDGPU::BI__builtin_amdgcn_sqrt: case AMDGPU::BI__builtin_amdgcn_sqrtf: case AMDGPU::BI__builtin_amdgcn_sqrth: + case AMDGPU::BI__builtin_amdgcn_sqrt_bf16: return emitBuiltinWithOneOverloadedType<1>(*this, E, Intrinsic::amdgcn_sqrt); case AMDGPU::BI__builtin_amdgcn_rsq: case AMDGPU::BI__builtin_amdgcn_rsqf: case AMDGPU::BI__builtin_amdgcn_rsqh: + case AMDGPU::BI__builtin_amdgcn_rsq_bf16: return emitBuiltinWithOneOverloadedType<1>(*this, E, Intrinsic::amdgcn_rsq); case AMDGPU::BI__builtin_amdgcn_rsq_clamp: case AMDGPU::BI__builtin_amdgcn_rsq_clampf: @@ -428,15 +430,19 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, Intrinsic::amdgcn_rsq_clamp); case AMDGPU::BI__builtin_amdgcn_sinf: case AMDGPU::BI__builtin_amdgcn_sinh: + case AMDGPU::BI__builtin_amdgcn_sin_bf16: return emitBuiltinWithOneOverloadedType<1>(*this, E, Intrinsic::amdgcn_sin); case AMDGPU::BI__builtin_amdgcn_cosf: case AMDGPU::BI__builtin_amdgcn_cosh: + case AMDGPU::BI__builtin_amdgcn_cos_bf16: return emitBuiltinWithOneOverloadedType<1>(*this, E, Intrinsic::amdgcn_cos); case AMDGPU::BI__builtin_amdgcn_dispatch_ptr: return EmitAMDGPUDispatchPtr(*this, E); case AMDGPU::BI__builtin_amdgcn_logf: + case AMDGPU::BI__builtin_amdgcn_log_bf16: return emitBuiltinWithOneOverloadedType<1>(*this, E, Intrinsic::amdgcn_log); case AMDGPU::BI__builtin_amdgcn_exp2f: + case AMDGPU::BI__builtin_amdgcn_exp2_bf16: return emitBuiltinWithOneOverloadedType<1>(*this, E, Intrinsic::amdgcn_exp2); case AMDGPU::BI__builtin_amdgcn_log_clampf: @@ -498,6 +504,8 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, Function *F = CGM.getIntrinsic(Intrinsic::amdgcn_ballot, { ResultType }); return Builder.CreateCall(F, { Src }); } + case AMDGPU::BI__builtin_amdgcn_tanhf: + case AMDGPU::BI__builtin_amdgcn_tanhh: case AMDGPU::BI__builtin_amdgcn_tanh_bf16: return emitBuiltinWithOneOverloadedType<1>(*this, E, Intrinsic::amdgcn_tanh); @@ -847,6 +855,7 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, case AMDGPU::BI__builtin_amdgcn_wmma_f32_16x16x128_bf8_fp8: case AMDGPU::BI__builtin_amdgcn_wmma_f32_16x16x128_bf8_bf8: case AMDGPU::BI__builtin_amdgcn_wmma_i32_16x16x64_iu8: + case AMDGPU::BI__builtin_amdgcn_wmma_f32_16x16x128_f8f6f4: case AMDGPU::BI__builtin_amdgcn_wmma_f32_32x16x128_f4: case AMDGPU::BI__builtin_amdgcn_swmmac_f32_16x16x64_f16: case AMDGPU::BI__builtin_amdgcn_swmmac_f32_16x16x64_bf16: @@ -1110,6 +1119,10 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, ArgsForMatchingMatrixTypes = {4, 1}; BuiltinWMMAOp = Intrinsic::amdgcn_wmma_i32_16x16x64_iu8; break; + case AMDGPU::BI__builtin_amdgcn_wmma_f32_16x16x128_f8f6f4: + ArgsForMatchingMatrixTypes = {5, 1, 3}; + BuiltinWMMAOp = Intrinsic::amdgcn_wmma_f32_16x16x128_f8f6f4; + break; case AMDGPU::BI__builtin_amdgcn_wmma_f32_32x16x128_f4: ArgsForMatchingMatrixTypes = {3, 0, 1}; BuiltinWMMAOp = Intrinsic::amdgcn_wmma_f32_32x16x128_f4; diff --git a/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp b/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp index 16243951c7bec..243aad8bf7083 100644 --- a/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp @@ -58,6 +58,18 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID, /*ReturnType=*/I->getType(), Intrinsic::spv_reflect, ArrayRef{I, N}, nullptr, "spv.reflect"); } + case SPIRV::BI__builtin_spirv_refract: { + Value *I = EmitScalarExpr(E->getArg(0)); + Value *N = EmitScalarExpr(E->getArg(1)); + Value *eta = EmitScalarExpr(E->getArg(2)); + assert(E->getArg(0)->getType()->hasFloatingRepresentation() && + E->getArg(1)->getType()->hasFloatingRepresentation() && + E->getArg(2)->getType()->isFloatingType() && + "refract operands must have a float representation"); + return Builder.CreateIntrinsic( + /*ReturnType=*/I->getType(), Intrinsic::spv_refract, + ArrayRef{I, N, eta}, nullptr, "spv.refract"); + } case SPIRV::BI__builtin_spirv_smoothstep: { Value *Min = EmitScalarExpr(E->getArg(0)); Value *Max = EmitScalarExpr(E->getArg(1)); diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 0b712ac2dabc4..abb91486e7ee6 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -2470,13 +2470,12 @@ GetSSETypeAtOffset(llvm::Type *IRType, unsigned IROffset, return llvm::Type::getDoubleTy(getVMContext()); } - /// GetINTEGERTypeAtOffset - The ABI specifies that a value should be passed in -/// an 8-byte GPR. This means that we either have a scalar or we are talking -/// about the high or low part of an up-to-16-byte struct. This routine picks -/// the best LLVM IR type to represent this, which may be i64 or may be anything -/// else that the backend will pass in a GPR that works better (e.g. i8, %foo*, -/// etc). +/// one or more 8-byte GPRs. This means that we either have a scalar or we are +/// talking about the high and/or low part of an up-to-16-byte struct. This +/// routine picks the best LLVM IR type to represent this, which may be i64 or +/// may be anything else that the backend will pass in GPRs that works better +/// (e.g. i8, %foo*, etc). /// /// PrefType is an LLVM IR type that corresponds to (part of) the IR type for /// the source type. IROffset is an offset in bytes into the LLVM IR type that @@ -2534,6 +2533,13 @@ GetINTEGERTypeAtOffset(llvm::Type *IRType, unsigned IROffset, SourceOffset); } + // if we have a 128-bit integer, we can pass it safely using an i128 + // so we return that + if (IRType->isIntegerTy(128)) { + assert(IROffset == 0); + return IRType; + } + // Okay, we don't have any better idea of what to pass, so we pass this in an // integer register that isn't too big to fit the rest of the struct. unsigned TySizeInBytes = @@ -2591,8 +2597,7 @@ GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type *Hi, return Result; } -ABIArgInfo X86_64ABIInfo:: -classifyReturnType(QualType RetTy) const { +ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy) const { // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the // classification algorithm. X86_64ABIInfo::Class Lo, Hi; @@ -2638,6 +2643,12 @@ classifyReturnType(QualType RetTy) const { isPromotableIntegerTypeForABI(RetTy)) return ABIArgInfo::getExtend(RetTy); } + + if (ResType->isIntegerTy(128)) { + // i128 are passed directly + assert(Hi == Integer); + return ABIArgInfo::getDirect(ResType); + } break; // AMD64-ABI 3.2.3p4: Rule 4. If the class is SSE, the next @@ -2783,6 +2794,11 @@ X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned freeIntRegs, return ABIArgInfo::getExtend(Ty, CGT.ConvertType(Ty)); } + if (ResType->isIntegerTy(128)) { + assert(Hi == Integer); + ++neededInt; + return ABIArgInfo::getDirect(ResType); + } break; // AMD64-ABI 3.2.3p3: Rule 3. If the class is SSE, the next diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index ec1135eecd401..ff2f92d1a94c8 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -68,6 +68,7 @@ #include "clang/Driver/Types.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" @@ -83,6 +84,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ExitCodes.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/FileUtilities.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/MD5.h" #include "llvm/Support/Path.h" @@ -109,65 +111,6 @@ using namespace clang::driver; using namespace clang; using namespace llvm::opt; -static std::optional getOffloadTargetTriple(const Driver &D, - const ArgList &Args) { - auto OffloadTargets = Args.getAllArgValues(options::OPT_offload_EQ); - // Offload compilation flow does not support multiple targets for now. We - // need the HIPActionBuilder (and possibly the CudaActionBuilder{,Base}too) - // to support multiple tool chains first. - switch (OffloadTargets.size()) { - default: - D.Diag(diag::err_drv_only_one_offload_target_supported); - return std::nullopt; - case 0: - D.Diag(diag::err_drv_invalid_or_unsupported_offload_target) << ""; - return std::nullopt; - case 1: - break; - } - return llvm::Triple(OffloadTargets[0]); -} - -static std::optional -getNVIDIAOffloadTargetTriple(const Driver &D, const ArgList &Args, - const llvm::Triple &HostTriple) { - if (!Args.hasArg(options::OPT_offload_EQ)) { - return llvm::Triple(HostTriple.isArch64Bit() ? "nvptx64-nvidia-cuda" - : "nvptx-nvidia-cuda"); - } - auto TT = getOffloadTargetTriple(D, Args); - if (TT && (TT->getArch() == llvm::Triple::spirv32 || - TT->getArch() == llvm::Triple::spirv64)) { - if (Args.hasArg(options::OPT_emit_llvm)) - return TT; - D.Diag(diag::err_drv_cuda_offload_only_emit_bc); - return std::nullopt; - } - D.Diag(diag::err_drv_invalid_or_unsupported_offload_target) << TT->str(); - return std::nullopt; -} - -static std::optional -getHIPOffloadTargetTriple(const Driver &D, const ArgList &Args) { - if (!Args.hasArg(options::OPT_offload_EQ)) { - auto OffloadArchs = Args.getAllArgValues(options::OPT_offload_arch_EQ); - if (llvm::is_contained(OffloadArchs, "amdgcnspirv") && - OffloadArchs.size() == 1) - return llvm::Triple("spirv64-amd-amdhsa"); - return llvm::Triple("amdgcn-amd-amdhsa"); // Default HIP triple. - } - auto TT = getOffloadTargetTriple(D, Args); - if (!TT) - return std::nullopt; - if (TT->isAMDGCN() && TT->getVendor() == llvm::Triple::AMD && - TT->getOS() == llvm::Triple::AMDHSA) - return TT; - if (TT->getArch() == llvm::Triple::spirv64) - return TT; - D.Diag(diag::err_drv_invalid_or_unsupported_offload_target) << TT->str(); - return std::nullopt; -} - template static bool usesInput(const ArgList &Args, F &&Fn) { return llvm::any_of(Args, [&](Arg *A) { return (A->getOption().matches(options::OPT_x) && @@ -458,6 +401,44 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, return FinalPhase; } +llvm::Expected> +Driver::executeProgram(llvm::ArrayRef Args) const { + llvm::SmallString<64> OutputFile; + llvm::sys::fs::createTemporaryFile("driver-program", "txt", OutputFile, + llvm::sys::fs::OF_Text); + llvm::FileRemover OutputRemover(OutputFile.c_str()); + std::optional Redirects[] = { + {""}, + OutputFile.str(), + {""}, + }; + + std::string ErrorMessage; + int SecondsToWait = 60; + if (std::optional Str = + llvm::sys::Process::GetEnv("CLANG_TOOLCHAIN_PROGRAM_TIMEOUT")) { + if (!llvm::to_integer(*Str, SecondsToWait)) + return llvm::createStringError(std::error_code(), + "CLANG_TOOLCHAIN_PROGRAM_TIMEOUT expected " + "an integer, got '" + + *Str + "'"); + SecondsToWait = std::max(SecondsToWait, 0); // infinite + } + StringRef Executable = Args[0]; + if (llvm::sys::ExecuteAndWait(Executable, Args, {}, Redirects, SecondsToWait, + /*MemoryLimit=*/0, &ErrorMessage)) + return llvm::createStringError(std::error_code(), + Executable + ": " + ErrorMessage); + + llvm::ErrorOr> OutputBuf = + llvm::MemoryBuffer::getFile(OutputFile.c_str()); + if (!OutputBuf) + return llvm::createStringError(OutputBuf.getError(), + "Failed to read stdout of " + Executable + + ": " + OutputBuf.getError().message()); + return std::move(*OutputBuf); +} + static Arg *MakeInputArg(DerivedArgList &Args, const OptTable &Opts, StringRef Value, bool Claim = true) { Arg *A = new Arg(Opts.getOption(options::OPT_INPUT), Value, @@ -921,250 +902,265 @@ Driver::OpenMPRuntimeKind Driver::getOpenMPRuntime(const ArgList &Args) const { return RT; } -static llvm::Triple getSYCLDeviceTriple(StringRef TargetArch) { - SmallVector SYCLAlias = {"spir", "spir64", "spirv", "spirv32", - "spirv64"}; - if (llvm::is_contained(SYCLAlias, TargetArch)) { - llvm::Triple TargetTriple; - TargetTriple.setArchName(TargetArch); - TargetTriple.setVendor(llvm::Triple::UnknownVendor); - TargetTriple.setOS(llvm::Triple::UnknownOS); - return TargetTriple; - } - return llvm::Triple(TargetArch); +// Handles `native` offload architectures by using the 'offload-arch' utility. +static llvm::SmallVector +getSystemOffloadArchs(Compilation &C, Action::OffloadKind Kind) { + StringRef Program = C.getArgs().getLastArgValue( + options::OPT_offload_arch_tool_EQ, "offload-arch"); + + SmallVector GPUArchs; + if (llvm::ErrorOr Executable = + llvm::sys::findProgramByName(Program)) { + llvm::SmallVector Args{*Executable}; + if (Kind == Action::OFK_HIP) + Args.push_back("--only=amdgpu"); + else if (Kind == Action::OFK_Cuda) + Args.push_back("--only=nvptx"); + auto StdoutOrErr = C.getDriver().executeProgram(Args); + + if (!StdoutOrErr) { + C.getDriver().Diag(diag::err_drv_undetermined_gpu_arch) + << Action::GetOffloadKindName(Kind) << StdoutOrErr.takeError() + << "--offload-arch"; + return GPUArchs; + } + if ((*StdoutOrErr)->getBuffer().empty()) { + C.getDriver().Diag(diag::err_drv_undetermined_gpu_arch) + << Action::GetOffloadKindName(Kind) << "No GPU detected in the system" + << "--offload-arch"; + return GPUArchs; + } + + for (StringRef Arch : llvm::split((*StdoutOrErr)->getBuffer(), "\n")) + if (!Arch.empty()) + GPUArchs.push_back(Arch.str()); + } else { + C.getDriver().Diag(diag::err_drv_command_failure) << "offload-arch"; + } + return GPUArchs; } -static bool addSYCLDefaultTriple(Compilation &C, - SmallVectorImpl &SYCLTriples) { - // Check current set of triples to see if the default has already been set. - for (const auto &SYCLTriple : SYCLTriples) { - if (SYCLTriple.getSubArch() == llvm::Triple::NoSubArch && - SYCLTriple.isSPIROrSPIRV()) - return false; +// Attempts to infer the correct offloading toolchain triple by looking at the +// requested offloading kind and architectures. +static llvm::DenseSet +inferOffloadToolchains(Compilation &C, Action::OffloadKind Kind) { + std::set Archs; + for (Arg *A : C.getInputArgs()) { + for (StringRef Arch : A->getValues()) { + if (A->getOption().matches(options::OPT_offload_arch_EQ)) { + if (Arch == "native") { + for (StringRef Str : getSystemOffloadArchs(C, Kind)) + Archs.insert(Str.str()); + } else { + Archs.insert(Arch.str()); + } + } else if (A->getOption().matches(options::OPT_no_offload_arch_EQ)) { + if (Arch == "all") + Archs.clear(); + else + Archs.erase(Arch.str()); + } + } } - // Add the default triple as it was not found. - llvm::Triple DefaultTriple = getSYCLDeviceTriple( - C.getDefaultToolChain().getTriple().isArch32Bit() ? "spirv32" - : "spirv64"); - SYCLTriples.insert(SYCLTriples.begin(), DefaultTriple); - return true; + + llvm::DenseSet Triples; + for (llvm::StringRef Arch : Archs) { + OffloadArch ID = StringToOffloadArch(Arch); + if (ID == OffloadArch::UNKNOWN) + ID = StringToOffloadArch( + getProcessorFromTargetID(llvm::Triple("amdgcn-amd-amdhsa"), Arch)); + + if (Kind == Action::OFK_HIP && !IsAMDOffloadArch(ID)) { + C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch) + << "HIP" << Arch; + return llvm::DenseSet(); + } + if (Kind == Action::OFK_Cuda && !IsNVIDIAOffloadArch(ID)) { + C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch) + << "CUDA" << Arch; + return llvm::DenseSet(); + } + if (Kind == Action::OFK_OpenMP && + (ID == OffloadArch::UNKNOWN || ID == OffloadArch::UNUSED)) { + C.getDriver().Diag(clang::diag::err_drv_failed_to_deduce_target_from_arch) + << Arch; + return llvm::DenseSet(); + } + if (ID == OffloadArch::UNKNOWN || ID == OffloadArch::UNUSED) { + C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch) + << "offload" << Arch; + return llvm::DenseSet(); + } + + StringRef Triple; + if (ID == OffloadArch::AMDGCNSPIRV) + Triple = "spirv64-amd-amdhsa"; + else if (IsNVIDIAOffloadArch(ID)) + Triple = C.getDefaultToolChain().getTriple().isArch64Bit() + ? "nvptx64-nvidia-cuda" + : "nvptx-nvidia-cuda"; + else if (IsAMDOffloadArch(ID)) + Triple = "amdgcn-amd-amdhsa"; + else + continue; + + // Make a new argument that dispatches this argument to the appropriate + // toolchain. This is required when we infer it and create potentially + // incompatible toolchains from the global option. + Option Opt = C.getDriver().getOpts().getOption(options::OPT_Xarch__); + unsigned Index = C.getArgs().getBaseArgs().MakeIndex("-Xarch_"); + Arg *A = new Arg(Opt, C.getArgs().getArgString(Index), Index, + C.getArgs().MakeArgString(Triple.split("-").first), + C.getArgs().MakeArgString("--offload-arch=" + Arch)); + C.getArgs().append(A); + Triples.insert(Triple); + } + + // Infer the default target triple if no specific architectures are given. + if (Archs.empty() && Kind == Action::OFK_HIP) + Triples.insert("amdgcn-amd-amdhsa"); + else if (Archs.empty() && Kind == Action::OFK_Cuda) + Triples.insert(C.getDefaultToolChain().getTriple().isArch64Bit() + ? "nvptx64-nvidia-cuda" + : "nvptx-nvidia-cuda"); + else if (Archs.empty() && Kind == Action::OFK_SYCL) + Triples.insert(C.getDefaultToolChain().getTriple().isArch64Bit() + ? "spirv64-unknown-unknown" + : "spirv32-unknown-unknown"); + + // We need to dispatch these to the appropriate toolchain now. + C.getArgs().eraseArg(options::OPT_offload_arch_EQ); + C.getArgs().eraseArg(options::OPT_no_offload_arch_EQ); + + return Triples; } void Driver::CreateOffloadingDeviceToolChains(Compilation &C, InputList &Inputs) { - - // - // CUDA/HIP - // - // We need to generate a CUDA/HIP toolchain if any of the inputs has a CUDA - // or HIP type. However, mixed CUDA/HIP compilation is not supported. + bool UseLLVMOffload = C.getInputArgs().hasArg( + options::OPT_foffload_via_llvm, options::OPT_fno_offload_via_llvm, false); bool IsCuda = - llvm::any_of(Inputs, [](std::pair &I) { - return types::isCuda(I.first); - }); - bool IsHIP = llvm::any_of(Inputs, [](std::pair &I) { - return types::isHIP(I.first); - }) || - C.getInputArgs().hasArg(options::OPT_hip_link) || - C.getInputArgs().hasArg(options::OPT_hipstdpar); - bool UseLLVMOffload = C.getInputArgs().hasArg( - options::OPT_foffload_via_llvm, options::OPT_fno_offload_via_llvm, false); - if (IsCuda && IsHIP) { - Diag(clang::diag::err_drv_mix_cuda_hip); + return types::isCuda(I.first); + }) && + !UseLLVMOffload; + bool IsHIP = + (llvm::any_of(Inputs, + [](std::pair &I) { + return types::isHIP(I.first); + }) || + C.getInputArgs().hasArg(options::OPT_hip_link) || + C.getInputArgs().hasArg(options::OPT_hipstdpar)) && + !UseLLVMOffload; + bool IsSYCL = C.getInputArgs().hasFlag(options::OPT_fsycl, + options::OPT_fno_sycl, false); + bool IsOpenMPOffloading = + UseLLVMOffload || + (C.getInputArgs().hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, + options::OPT_fno_openmp, false) && + (C.getInputArgs().hasArg(options::OPT_offload_targets_EQ) || + (C.getInputArgs().hasArg(options::OPT_offload_arch_EQ) && + !(IsCuda || IsHIP)))); + + llvm::SmallSet Kinds; + const std::pair ActiveKinds[] = { + {IsCuda, Action::OFK_Cuda}, + {IsHIP, Action::OFK_HIP}, + {IsOpenMPOffloading, Action::OFK_OpenMP}, + {IsSYCL, Action::OFK_SYCL}}; + for (const auto &[Active, Kind] : ActiveKinds) + if (Active) + Kinds.insert(Kind); + + // We currently don't support any kind of mixed offloading. + if (Kinds.size() > 1) { + Diag(clang::diag::err_drv_mix_offload) + << Action::GetOffloadKindName(*Kinds.begin()).upper() + << Action::GetOffloadKindName(*(++Kinds.begin())).upper(); return; } - if (IsCuda && !UseLLVMOffload) { - auto CudaTriple = getNVIDIAOffloadTargetTriple( - *this, C.getInputArgs(), C.getDefaultToolChain().getTriple()); - if (!CudaTriple) - return; - - auto &TC = - getOffloadToolChain(C.getInputArgs(), Action::OFK_Cuda, *CudaTriple, - C.getDefaultToolChain().getTriple()); - - // Emit a warning if the detected CUDA version is too new. - const CudaInstallationDetector &CudaInstallation = - static_cast(TC).CudaInstallation; - if (CudaInstallation.isValid()) - CudaInstallation.WarnIfUnsupportedVersion(); - C.addOffloadDeviceToolChain(&TC, Action::OFK_Cuda); - OffloadArchs[&TC] = getOffloadArchs(C, C.getArgs(), Action::OFK_Cuda, &TC, - /*SpecificToolchain=*/true); - } else if (IsHIP && !UseLLVMOffload) { - if (auto *OMPTargetArg = - C.getInputArgs().getLastArg(options::OPT_offload_targets_EQ)) { - Diag(clang::diag::err_drv_unsupported_opt_for_language_mode) - << OMPTargetArg->getSpelling() << "HIP"; - return; - } - - auto HIPTriple = getHIPOffloadTargetTriple(*this, C.getInputArgs()); - if (!HIPTriple) - return; - - auto &TC = - getOffloadToolChain(C.getInputArgs(), Action::OFK_HIP, *HIPTriple, - C.getDefaultToolChain().getTriple()); - C.addOffloadDeviceToolChain(&TC, Action::OFK_HIP); - - // TODO: Fix 'amdgcnspirv' handling with the new driver. - if (C.getInputArgs().hasFlag(options::OPT_offload_new_driver, - options::OPT_no_offload_new_driver, false)) - OffloadArchs[&TC] = getOffloadArchs(C, C.getArgs(), Action::OFK_HIP, &TC, - /*SpecificToolchain=*/true); - } + // Initialize the compilation identifier used for unique CUDA / HIP names. if (IsCuda || IsHIP) CUIDOpts = CUIDOptions(C.getArgs(), *this); - // - // OpenMP - // - // We need to generate an OpenMP toolchain if the user specified targets with - // the -fopenmp-targets option or used --offload-arch with OpenMP enabled. - bool IsOpenMPOffloading = - ((IsCuda || IsHIP) && UseLLVMOffload) || - (C.getInputArgs().hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, - options::OPT_fno_openmp, false) && - (C.getInputArgs().hasArg(options::OPT_offload_targets_EQ) || - C.getInputArgs().hasArg(options::OPT_offload_arch_EQ))); - if (IsOpenMPOffloading) { - // We expect that -fopenmp-targets is always used in conjunction with the - // option -fopenmp specifying a valid runtime with offloading support, i.e. - // libomp or libiomp. - OpenMPRuntimeKind RuntimeKind = getOpenMPRuntime(C.getInputArgs()); - if (RuntimeKind != OMPRT_OMP && RuntimeKind != OMPRT_IOMP5) { - Diag(clang::diag::err_drv_expecting_fopenmp_with_fopenmp_targets); - return; - } - - // If the user specified -fopenmp-targets= we create a toolchain for each - // valid triple. Otherwise, if only --offload-arch= was specified we instead - // attempt to derive the appropriate toolchains from the arguments. - if (Arg *OpenMPTargets = - C.getInputArgs().getLastArg(options::OPT_offload_targets_EQ)) { - if (OpenMPTargets && !OpenMPTargets->getNumValues()) { - Diag(clang::diag::warn_drv_empty_joined_argument) - << OpenMPTargets->getAsString(C.getInputArgs()); + // Get the list of requested offloading toolchains. If they were not + // explicitly specified we will infer them based on the offloading language + // and requested architectures. + std::multiset Triples; + if (C.getInputArgs().hasArg(options::OPT_offload_targets_EQ)) { + std::vector ArgValues = + C.getInputArgs().getAllArgValues(options::OPT_offload_targets_EQ); + for (llvm::StringRef Target : ArgValues) + Triples.insert(C.getInputArgs().MakeArgString(Target)); + + if (ArgValues.empty()) + Diag(clang::diag::warn_drv_empty_joined_argument) + << C.getInputArgs() + .getLastArg(options::OPT_offload_targets_EQ) + ->getAsString(C.getInputArgs()); + } else if (Kinds.size() > 0) { + for (Action::OffloadKind Kind : Kinds) { + llvm::DenseSet Derived = inferOffloadToolchains(C, Kind); + Triples.insert(Derived.begin(), Derived.end()); + } + } + + // Build an offloading toolchain for every requested target and kind. + llvm::StringMap FoundNormalizedTriples; + for (StringRef Target : Triples) { + // OpenMP offloading requires a compatible libomp. + if (Kinds.contains(Action::OFK_OpenMP)) { + OpenMPRuntimeKind RuntimeKind = getOpenMPRuntime(C.getInputArgs()); + if (RuntimeKind != OMPRT_OMP && RuntimeKind != OMPRT_IOMP5) { + Diag(clang::diag::err_drv_expecting_fopenmp_with_fopenmp_targets); return; } + } - // Make sure these show up in a deterministic order. - std::multiset OpenMPTriples; - for (StringRef T : OpenMPTargets->getValues()) - OpenMPTriples.insert(T); - - llvm::StringMap FoundNormalizedTriples; - for (StringRef T : OpenMPTriples) { - llvm::Triple TT(ToolChain::getOpenMPTriple(T)); - std::string NormalizedName = TT.normalize(); - - // Make sure we don't have a duplicate triple. - auto [TripleIt, Inserted] = - FoundNormalizedTriples.try_emplace(NormalizedName, T); - if (!Inserted) { - Diag(clang::diag::warn_drv_omp_offload_target_duplicate) - << T << TripleIt->second; - continue; - } - - // If the specified target is invalid, emit a diagnostic. - if (TT.getArch() == llvm::Triple::UnknownArch) { - Diag(clang::diag::err_drv_invalid_omp_target) << T; - continue; - } + // Certain options are not allowed when combined with SYCL compilation. + if (Kinds.contains(Action::OFK_SYCL)) { + for (auto ID : + {options::OPT_static_libstdcxx, options::OPT_ffreestanding}) + if (Arg *IncompatArg = C.getInputArgs().getLastArg(ID)) + Diag(clang::diag::err_drv_argument_not_allowed_with) + << IncompatArg->getSpelling() << "-fsycl"; + } - auto &TC = getOffloadToolChain(C.getInputArgs(), Action::OFK_OpenMP, TT, - C.getDefaultToolChain().getTriple()); - C.addOffloadDeviceToolChain(&TC, Action::OFK_OpenMP); - OffloadArchs[&TC] = - getOffloadArchs(C, C.getArgs(), Action::OFK_OpenMP, &TC, - /*SpecificToolchain=*/true); - } - } else if (C.getInputArgs().hasArg(options::OPT_offload_arch_EQ) && - ((!IsHIP && !IsCuda) || UseLLVMOffload)) { - llvm::Triple AMDTriple("amdgcn-amd-amdhsa"); - llvm::Triple NVPTXTriple("nvptx64-nvidia-cuda"); - - for (StringRef Arch : - C.getInputArgs().getAllArgValues(options::OPT_offload_arch_EQ)) { - bool IsNVPTX = IsNVIDIAOffloadArch( - StringToOffloadArch(getProcessorFromTargetID(NVPTXTriple, Arch))); - bool IsAMDGPU = IsAMDOffloadArch( - StringToOffloadArch(getProcessorFromTargetID(AMDTriple, Arch))); - if (!IsNVPTX && !IsAMDGPU && !Arch.empty() && - !Arch.equals_insensitive("native")) { - Diag(clang::diag::err_drv_failed_to_deduce_target_from_arch) << Arch; - return; - } + // Create a device toolchain for every specified kind and triple. + for (Action::OffloadKind Kind : Kinds) { + llvm::Triple TT = Kind == Action::OFK_OpenMP + ? ToolChain::getOpenMPTriple(Target) + : llvm::Triple(Target); + if (TT.getArch() == llvm::Triple::ArchType::UnknownArch) { + Diag(diag::err_drv_invalid_or_unsupported_offload_target) << TT.str(); + continue; } - // Attempt to deduce the offloading triple from the set of architectures. - // We can only correctly deduce NVPTX / AMDGPU triples currently. - for (const llvm::Triple &TT : {AMDTriple, NVPTXTriple}) { - auto &TC = getOffloadToolChain(C.getInputArgs(), Action::OFK_OpenMP, TT, - C.getDefaultToolChain().getTriple()); - - llvm::SmallVector Archs = - getOffloadArchs(C, C.getArgs(), Action::OFK_OpenMP, &TC, - /*SpecificToolchain=*/false); - if (!Archs.empty()) { - C.addOffloadDeviceToolChain(&TC, Action::OFK_OpenMP); - OffloadArchs[&TC] = Archs; - } + std::string NormalizedName = TT.normalize(); + auto [TripleIt, Inserted] = + FoundNormalizedTriples.try_emplace(NormalizedName, Target); + if (!Inserted) { + Diag(clang::diag::warn_drv_omp_offload_target_duplicate) + << Target << TripleIt->second; + continue; } - // If the set is empty then we failed to find a native architecture. - auto TCRange = C.getOffloadToolChains(Action::OFK_OpenMP); - if (TCRange.first == TCRange.second) - Diag(clang::diag::err_drv_failed_to_deduce_target_from_arch) - << "native"; - } - } else if (C.getInputArgs().hasArg(options::OPT_offload_targets_EQ)) { - Diag(clang::diag::err_drv_expecting_fopenmp_with_fopenmp_targets); - return; - } + auto &TC = getOffloadToolChain(C.getInputArgs(), Kind, TT, + C.getDefaultToolChain().getTriple()); - // We need to generate a SYCL toolchain if the user specified -fsycl. - bool IsSYCL = C.getInputArgs().hasFlag(options::OPT_fsycl, - options::OPT_fno_sycl, false); - - auto argSYCLIncompatible = [&](OptSpecifier OptId) { - if (!IsSYCL) - return; - if (Arg *IncompatArg = C.getInputArgs().getLastArg(OptId)) - Diag(clang::diag::err_drv_argument_not_allowed_with) - << IncompatArg->getSpelling() << "-fsycl"; - }; - // -static-libstdc++ is not compatible with -fsycl. - argSYCLIncompatible(options::OPT_static_libstdcxx); - // -ffreestanding cannot be used with -fsycl - argSYCLIncompatible(options::OPT_ffreestanding); - - llvm::SmallVector UniqueSYCLTriplesVec; - - if (IsSYCL) { - addSYCLDefaultTriple(C, UniqueSYCLTriplesVec); + // Emit a warning if the detected CUDA version is too new. + if (Kind == Action::OFK_Cuda) { + auto &CudaInstallation = + static_cast(TC).CudaInstallation; + if (CudaInstallation.isValid()) + CudaInstallation.WarnIfUnsupportedVersion(); + } - // We'll need to use the SYCL and host triples as the key into - // getOffloadingDeviceToolChain, because the device toolchains we're - // going to create will depend on both. - const ToolChain *HostTC = C.getSingleOffloadToolChain(); - for (const auto &TT : UniqueSYCLTriplesVec) { - auto &TC = getOffloadToolChain(C.getInputArgs(), Action::OFK_SYCL, TT, - HostTC->getTriple()); - C.addOffloadDeviceToolChain(&TC, Action::OFK_SYCL); - OffloadArchs[&TC] = getOffloadArchs(C, C.getArgs(), Action::OFK_SYCL, &TC, - /*SpecificToolchain=*/true); + C.addOffloadDeviceToolChain(&TC, Kind); } } - - // - // TODO: Add support for other offloading programming models here. - // } bool Driver::loadZOSCustomizationFile(llvm::cl::ExpansionContext &ExpCtx) { @@ -3306,9 +3302,6 @@ class OffloadingActionBuilder final { // architecture. If we are in host-only mode we return 'success' so that // the host uses the CUDA offload kind. if (auto *IA = dyn_cast(HostAction)) { - assert(!GpuArchList.empty() && - "We should have at least one GPU architecture."); - // If the host input is not CUDA or HIP, we don't need to bother about // this input. if (!(IA->getType() == types::TY_CUDA || @@ -3408,10 +3401,6 @@ class OffloadingActionBuilder final { CudaDeviceActions.clear(); } - /// Get canonicalized offload arch option. \returns empty StringRef if the - /// option is invalid. - virtual StringRef getCanonicalOffloadArch(StringRef Arch) = 0; - virtual std::optional> getConflictOffloadArchCombination(const std::set &GpuArchs) = 0; @@ -3440,91 +3429,25 @@ class OffloadingActionBuilder final { return true; } - ToolChains.push_back( - AssociatedOffloadKind == Action::OFK_Cuda - ? C.getSingleOffloadToolChain() - : C.getSingleOffloadToolChain()); - - CompileHostOnly = C.getDriver().offloadHostOnly(); - EmitLLVM = Args.getLastArg(options::OPT_emit_llvm); - EmitAsm = Args.getLastArg(options::OPT_S); - - // --offload and --offload-arch options are mutually exclusive. - if (Args.hasArgNoClaim(options::OPT_offload_EQ) && - Args.hasArgNoClaim(options::OPT_offload_arch_EQ, - options::OPT_no_offload_arch_EQ)) { - C.getDriver().Diag(diag::err_opt_not_valid_with_opt) << "--offload-arch" - << "--offload"; - } - - // Collect all offload arch parameters, removing duplicates. std::set GpuArchs; - bool Error = false; - const ToolChain &TC = *ToolChains.front(); - for (Arg *A : C.getArgsForToolChain(&TC, /*BoundArch=*/"", - AssociatedOffloadKind)) { - if (!(A->getOption().matches(options::OPT_offload_arch_EQ) || - A->getOption().matches(options::OPT_no_offload_arch_EQ))) - continue; - A->claim(); - - for (StringRef ArchStr : llvm::split(A->getValue(), ",")) { - if (A->getOption().matches(options::OPT_no_offload_arch_EQ) && - ArchStr == "all") { - GpuArchs.clear(); - } else if (ArchStr == "native") { - auto GPUsOrErr = ToolChains.front()->getSystemGPUArchs(Args); - if (!GPUsOrErr) { - TC.getDriver().Diag(diag::err_drv_undetermined_gpu_arch) - << llvm::Triple::getArchTypeName(TC.getArch()) - << llvm::toString(GPUsOrErr.takeError()) << "--offload-arch"; - continue; - } + for (Action::OffloadKind Kind : {Action::OFK_Cuda, Action::OFK_HIP}) { + for (auto &I : llvm::make_range(C.getOffloadToolChains(Kind))) { + ToolChains.push_back(I.second); - for (auto GPU : *GPUsOrErr) { - GpuArchs.insert(Args.MakeArgString(GPU)); - } - } else { - ArchStr = getCanonicalOffloadArch(ArchStr); - if (ArchStr.empty()) { - Error = true; - } else if (A->getOption().matches(options::OPT_offload_arch_EQ)) - GpuArchs.insert(ArchStr); - else if (A->getOption().matches(options::OPT_no_offload_arch_EQ)) - GpuArchs.erase(ArchStr); - else - llvm_unreachable("Unexpected option."); - } + for (auto Arch : + C.getDriver().getOffloadArchs(C, C.getArgs(), Kind, *I.second)) + GpuArchs.insert(Arch); } } - auto &&ConflictingArchs = getConflictOffloadArchCombination(GpuArchs); - if (ConflictingArchs) { - C.getDriver().Diag(clang::diag::err_drv_bad_offload_arch_combo) - << ConflictingArchs->first << ConflictingArchs->second; - C.setContainsError(); - return true; - } - - // Collect list of GPUs remaining in the set. for (auto Arch : GpuArchs) GpuArchList.push_back(Arch.data()); - // Default to sm_20 which is the lowest common denominator for - // supported GPUs. sm_20 code should work correctly, if - // suboptimally, on all newer GPUs. - if (GpuArchList.empty()) { - if (ToolChains.front()->getTriple().isSPIRV()) { - if (ToolChains.front()->getTriple().getVendor() == llvm::Triple::AMD) - GpuArchList.push_back(OffloadArch::AMDGCNSPIRV); - else - GpuArchList.push_back(OffloadArch::Generic); - } else { - GpuArchList.push_back(DefaultOffloadArch); - } - } + CompileHostOnly = C.getDriver().offloadHostOnly(); + EmitLLVM = Args.getLastArg(options::OPT_emit_llvm); + EmitAsm = Args.getLastArg(options::OPT_S); - return Error; + return false; } }; @@ -3538,15 +3461,6 @@ class OffloadingActionBuilder final { DefaultOffloadArch = OffloadArch::CudaDefault; } - StringRef getCanonicalOffloadArch(StringRef ArchStr) override { - OffloadArch Arch = StringToOffloadArch(ArchStr); - if (Arch == OffloadArch::UNKNOWN || !IsNVIDIAOffloadArch(Arch)) { - C.getDriver().Diag(clang::diag::err_drv_cuda_bad_gpu_arch) << ArchStr; - return StringRef(); - } - return OffloadArchToString(Arch); - } - std::optional> getConflictOffloadArchCombination( const std::set &GpuArchs) override { @@ -3705,24 +3619,6 @@ class OffloadingActionBuilder final { bool canUseBundlerUnbundler() const override { return true; } - StringRef getCanonicalOffloadArch(StringRef IdStr) override { - llvm::StringMap Features; - // getHIPOffloadTargetTriple() is known to return valid value as it has - // been called successfully in the CreateOffloadingDeviceToolChains(). - auto T = - (IdStr == "amdgcnspirv") - ? llvm::Triple("spirv64-amd-amdhsa") - : *getHIPOffloadTargetTriple(C.getDriver(), C.getInputArgs()); - auto ArchStr = parseTargetID(T, IdStr, &Features); - if (!ArchStr) { - C.getDriver().Diag(clang::diag::err_drv_bad_target_id) << IdStr; - C.setContainsError(); - return StringRef(); - } - auto CanId = getCanonicalTargetID(*ArchStr, Features); - return Args.MakeArgStringRef(CanId); - }; - std::optional> getConflictOffloadArchCombination( const std::set &GpuArchs) override { @@ -4715,23 +4611,20 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, static StringRef getCanonicalArchString(Compilation &C, const llvm::opt::DerivedArgList &Args, StringRef ArchStr, - const llvm::Triple &Triple, - bool SpecificToolchain) { + const llvm::Triple &Triple) { // Lookup the CUDA / HIP architecture string. Only report an error if we were // expecting the triple to be only NVPTX / AMDGPU. OffloadArch Arch = StringToOffloadArch(getProcessorFromTargetID(Triple, ArchStr)); if (Triple.isNVPTX() && (Arch == OffloadArch::UNKNOWN || !IsNVIDIAOffloadArch(Arch))) { - if (SpecificToolchain) - C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch) - << "CUDA" << ArchStr; + C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch) + << "CUDA" << ArchStr; return StringRef(); } else if (Triple.isAMDGPU() && (Arch == OffloadArch::UNKNOWN || !IsAMDOffloadArch(Arch))) { - if (SpecificToolchain) - C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch) - << "HIP" << ArchStr; + C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch) + << "HIP" << ArchStr; return StringRef(); } @@ -4767,11 +4660,7 @@ getConflictOffloadArchCombination(const llvm::DenseSet &Archs, llvm::SmallVector Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args, - Action::OffloadKind Kind, const ToolChain *TC, - bool SpecificToolchain) const { - if (!TC) - TC = &C.getDefaultToolChain(); - + Action::OffloadKind Kind, const ToolChain &TC) const { // --offload and --offload-arch options are mutually exclusive. if (Args.hasArgNoClaim(options::OPT_offload_EQ) && Args.hasArgNoClaim(options::OPT_offload_arch_EQ, @@ -4784,48 +4673,44 @@ Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args, } llvm::DenseSet Archs; - for (auto *Arg : C.getArgsForToolChain(TC, /*BoundArch=*/"", Kind)) { + for (auto *Arg : C.getArgsForToolChain(&TC, /*BoundArch=*/"", Kind)) { // Add or remove the seen architectures in order of appearance. If an // invalid architecture is given we simply exit. if (Arg->getOption().matches(options::OPT_offload_arch_EQ)) { for (StringRef Arch : Arg->getValues()) { if (Arch == "native" || Arch.empty()) { - auto GPUsOrErr = TC->getSystemGPUArchs(Args); + auto GPUsOrErr = TC.getSystemGPUArchs(Args); if (!GPUsOrErr) { - if (!SpecificToolchain) - llvm::consumeError(GPUsOrErr.takeError()); - else - TC->getDriver().Diag(diag::err_drv_undetermined_gpu_arch) - << llvm::Triple::getArchTypeName(TC->getArch()) - << llvm::toString(GPUsOrErr.takeError()) << "--offload-arch"; + TC.getDriver().Diag(diag::err_drv_undetermined_gpu_arch) + << llvm::Triple::getArchTypeName(TC.getArch()) + << llvm::toString(GPUsOrErr.takeError()) << "--offload-arch"; continue; } for (auto ArchStr : *GPUsOrErr) { - StringRef CanonicalStr = - getCanonicalArchString(C, Args, Args.MakeArgString(ArchStr), - TC->getTriple(), SpecificToolchain); + StringRef CanonicalStr = getCanonicalArchString( + C, Args, Args.MakeArgString(ArchStr), TC.getTriple()); if (!CanonicalStr.empty()) Archs.insert(CanonicalStr); - else if (SpecificToolchain) + else return llvm::SmallVector(); } } else { - StringRef CanonicalStr = getCanonicalArchString( - C, Args, Arch, TC->getTriple(), SpecificToolchain); + StringRef CanonicalStr = + getCanonicalArchString(C, Args, Arch, TC.getTriple()); if (!CanonicalStr.empty()) Archs.insert(CanonicalStr); - else if (SpecificToolchain) + else return llvm::SmallVector(); } } } else if (Arg->getOption().matches(options::OPT_no_offload_arch_EQ)) { - for (StringRef Arch : llvm::split(Arg->getValue(), ",")) { + for (StringRef Arch : Arg->getValues()) { if (Arch == "all") { Archs.clear(); } else { - StringRef ArchStr = getCanonicalArchString( - C, Args, Arch, TC->getTriple(), SpecificToolchain); + StringRef ArchStr = + getCanonicalArchString(C, Args, Arch, TC.getTriple()); Archs.erase(ArchStr); } } @@ -4833,28 +4718,30 @@ Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args, } if (auto ConflictingArchs = - getConflictOffloadArchCombination(Archs, TC->getTriple())) + getConflictOffloadArchCombination(Archs, TC.getTriple())) C.getDriver().Diag(clang::diag::err_drv_bad_offload_arch_combo) << ConflictingArchs->first << ConflictingArchs->second; - // Skip filling defaults if we're just querying what is availible. - if (SpecificToolchain && Archs.empty()) { + // Fill in the default architectures if not provided explicitly. + if (Archs.empty()) { if (Kind == Action::OFK_Cuda) { Archs.insert(OffloadArchToString(OffloadArch::CudaDefault)); } else if (Kind == Action::OFK_HIP) { - Archs.insert(OffloadArchToString(OffloadArch::HIPDefault)); + Archs.insert(OffloadArchToString(TC.getTriple().isSPIRV() + ? OffloadArch::Generic + : OffloadArch::HIPDefault)); } else if (Kind == Action::OFK_SYCL) { Archs.insert(StringRef()); } else if (Kind == Action::OFK_OpenMP) { // Accept legacy `-march` device arguments for OpenMP. - if (auto *Arg = C.getArgsForToolChain(TC, /*BoundArch=*/"", Kind) + if (auto *Arg = C.getArgsForToolChain(&TC, /*BoundArch=*/"", Kind) .getLastArg(options::OPT_march_EQ)) { Archs.insert(Arg->getValue()); } else { - auto ArchsOrErr = TC->getSystemGPUArchs(Args); + auto ArchsOrErr = TC.getSystemGPUArchs(Args); if (!ArchsOrErr) { - TC->getDriver().Diag(diag::err_drv_undetermined_gpu_arch) - << llvm::Triple::getArchTypeName(TC->getArch()) + TC.getDriver().Diag(diag::err_drv_undetermined_gpu_arch) + << llvm::Triple::getArchTypeName(TC.getArch()) << llvm::toString(ArchsOrErr.takeError()) << "--offload-arch"; } else if (!ArchsOrErr->empty()) { for (auto Arch : *ArchsOrErr) @@ -4934,7 +4821,7 @@ Action *Driver::BuildOffloadingActions(Compilation &C, // Get the product of all bound architectures and toolchains. SmallVector> TCAndArchs; for (const ToolChain *TC : ToolChains) { - for (StringRef Arch : OffloadArchs.lookup(TC)) { + for (StringRef Arch : getOffloadArchs(C, C.getArgs(), Kind, *TC)) { TCAndArchs.push_back(std::make_pair(TC, Arch)); DeviceActions.push_back( C.MakeAction(*InputArg, InputType, CUID)); @@ -4966,7 +4853,7 @@ Action *Driver::BuildOffloadingActions(Compilation &C, if (Kind == Action::OFK_SYCL && Phase == phases::Assemble) continue; - auto TCAndArch = TCAndArchs.begin(); + auto *TCAndArch = TCAndArchs.begin(); for (Action *&A : DeviceActions) { if (A->getType() == types::TY_Nothing) continue; @@ -5006,7 +4893,7 @@ Action *Driver::BuildOffloadingActions(Compilation &C, A = C.MakeAction(LinkerInput, types::TY_Image); } - auto TCAndArch = TCAndArchs.begin(); + auto *TCAndArch = TCAndArchs.begin(); for (Action *A : DeviceActions) { DDeps.add(*A, *TCAndArch->first, TCAndArch->second.data(), Kind); OffloadAction::DeviceDependences DDep; @@ -5131,11 +5018,13 @@ Action *Driver::ConstructPhaseAction( if (Args.hasArg(options::OPT_extract_api)) return C.MakeAction(Input, types::TY_API_INFO); - // With 'fexperimental-modules-reduced-bmi', we don't want to run the + // With 'fmodules-reduced-bmi', we don't want to run the // precompile phase unless the user specified '--precompile'. In the case // the '--precompile' flag is enabled, we will try to emit the reduced BMI // as a by product in GenerateModuleInterfaceAction. - if (Args.hasArg(options::OPT_modules_reduced_bmi) && + if (!Args.hasArg(options::OPT_fno_modules_reduced_bmi) && + (Input->getType() == driver::types::TY_CXXModule || + Input->getType() == driver::types::TY_PP_CXXModule) && !Args.getLastArg(options::OPT__precompile)) return Input; @@ -6323,7 +6212,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, // `-fmodule-output`. if (!AtTopLevel && isa(JA) && JA.getType() == types::TY_ModuleFile && SpecifiedModuleOutput) { - assert(!C.getArgs().hasArg(options::OPT_modules_reduced_bmi)); + assert(C.getArgs().hasArg(options::OPT_fno_modules_reduced_bmi)); return GetModuleOutputPath(C, JA, BaseInput); } diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 3f9b808b2722e..180452077dde1 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -104,44 +104,6 @@ ToolChain::ToolChain(const Driver &D, const llvm::Triple &T, addIfExists(getFilePaths(), Path); } -llvm::Expected> -ToolChain::executeToolChainProgram(StringRef Executable) const { - llvm::SmallString<64> OutputFile; - llvm::sys::fs::createTemporaryFile("toolchain-program", "txt", OutputFile, - llvm::sys::fs::OF_Text); - llvm::FileRemover OutputRemover(OutputFile.c_str()); - std::optional Redirects[] = { - {""}, - OutputFile.str(), - {""}, - }; - - std::string ErrorMessage; - int SecondsToWait = 60; - if (std::optional Str = - llvm::sys::Process::GetEnv("CLANG_TOOLCHAIN_PROGRAM_TIMEOUT")) { - if (!llvm::to_integer(*Str, SecondsToWait)) - return llvm::createStringError(std::error_code(), - "CLANG_TOOLCHAIN_PROGRAM_TIMEOUT expected " - "an integer, got '" + - *Str + "'"); - SecondsToWait = std::max(SecondsToWait, 0); // infinite - } - if (llvm::sys::ExecuteAndWait(Executable, {Executable}, {}, Redirects, - SecondsToWait, - /*MemoryLimit=*/0, &ErrorMessage)) - return llvm::createStringError(std::error_code(), - Executable + ": " + ErrorMessage); - - llvm::ErrorOr> OutputBuf = - llvm::MemoryBuffer::getFile(OutputFile.c_str()); - if (!OutputBuf) - return llvm::createStringError(OutputBuf.getError(), - "Failed to read stdout of " + Executable + - ": " + OutputBuf.getError().message()); - return std::move(*OutputBuf); -} - void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) { Triple.setEnvironment(Env); if (EffectiveTriple != llvm::Triple()) @@ -255,13 +217,25 @@ static void getAArch64MultilibFlags(const Driver &D, Result.push_back(ABIArg->getAsString(Args)); } + if (const Arg *A = Args.getLastArg(options::OPT_O_Group); + A && A->getOption().matches(options::OPT_O)) { + switch (A->getValue()[0]) { + case 's': + Result.push_back("-Os"); + break; + case 'z': + Result.push_back("-Oz"); + break; + } + } + processMultilibCustomFlags(Result, Args); } -static void getARMMultilibFlags(const Driver &D, - const llvm::Triple &Triple, - const llvm::opt::ArgList &Args, - Multilib::flags_list &Result) { +static void getARMMultilibFlags(const Driver &D, const llvm::Triple &Triple, + llvm::Reloc::Model RelocationModel, + const llvm::opt::ArgList &Args, + Multilib::flags_list &Result) { std::vector Features; llvm::ARM::FPUKind FPUKind = tools::arm::getARMTargetFeatures( D, Triple, Args, Features, false /*ForAs*/, true /*ForMultilib*/); @@ -304,6 +278,18 @@ static void getARMMultilibFlags(const Driver &D, llvm_unreachable("Invalid float ABI"); } + if (RelocationModel == llvm::Reloc::ROPI || + RelocationModel == llvm::Reloc::ROPI_RWPI) + Result.push_back("-fropi"); + else + Result.push_back("-fno-ropi"); + + if (RelocationModel == llvm::Reloc::RWPI || + RelocationModel == llvm::Reloc::ROPI_RWPI) + Result.push_back("-frwpi"); + else + Result.push_back("-fno-rwpi"); + const Arg *BranchProtectionArg = Args.getLastArgNoClaim(options::OPT_mbranch_protection_EQ); if (BranchProtectionArg) { @@ -320,6 +306,19 @@ static void getARMMultilibFlags(const Driver &D, if (Endian->getOption().matches(options::OPT_mbig_endian)) Result.push_back(Endian->getAsString(Args)); } + + if (const Arg *A = Args.getLastArg(options::OPT_O_Group); + A && A->getOption().matches(options::OPT_O)) { + switch (A->getValue()[0]) { + case 's': + Result.push_back("-Os"); + break; + case 'z': + Result.push_back("-Oz"); + break; + } + } + processMultilibCustomFlags(Result, Args); } @@ -344,6 +343,18 @@ ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const { const llvm::Triple Triple(ComputeEffectiveClangTriple(Args)); Result.push_back("--target=" + Triple.str()); + // A difference of relocation model (absolutely addressed data, PIC, Arm + // ROPI/RWPI) is likely to change whether a particular multilib variant is + // compatible with a given link. Determine the relocation model of the + // current link, so as to add appropriate multilib flags. + llvm::Reloc::Model RelocationModel; + unsigned PICLevel; + bool IsPIE; + { + RegisterEffectiveTriple TripleRAII(*this, Triple); + std::tie(RelocationModel, PICLevel, IsPIE) = ParsePICArgs(*this, Args); + } + switch (Triple.getArch()) { case llvm::Triple::aarch64: case llvm::Triple::aarch64_32: @@ -354,7 +365,7 @@ ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const { case llvm::Triple::armeb: case llvm::Triple::thumb: case llvm::Triple::thumbeb: - getARMMultilibFlags(D, Triple, Args, Result); + getARMMultilibFlags(D, Triple, RelocationModel, Args, Result); break; case llvm::Triple::riscv32: case llvm::Triple::riscv64: @@ -376,6 +387,12 @@ ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const { else Result.push_back("-fexceptions"); + if (RelocationModel == llvm::Reloc::PIC_) + Result.push_back(IsPIE ? (PICLevel > 1 ? "-fPIE" : "-fpie") + : (PICLevel > 1 ? "-fPIC" : "-fpic")); + else + Result.push_back("-fno-pic"); + // Sort and remove duplicates. std::sort(Result.begin(), Result.end()); Result.erase(llvm::unique(Result), Result.end()); diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp index 7fc34f451f183..0cd8819a92b66 100644 --- a/clang/lib/Driver/ToolChains/AMDGPU.cpp +++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp @@ -841,7 +841,7 @@ AMDGPUToolChain::getSystemGPUArchs(const ArgList &Args) const { else Program = GetProgramPath("amdgpu-arch"); - auto StdoutOrErr = executeToolChainProgram(Program); + auto StdoutOrErr = getDriver().executeProgram({Program}); if (!StdoutOrErr) return StdoutOrErr.takeError(); diff --git a/clang/lib/Driver/ToolChains/Arch/Sparc.cpp b/clang/lib/Driver/ToolChains/Arch/Sparc.cpp index 9595ee8383c85..504f110eac87c 100644 --- a/clang/lib/Driver/ToolChains/Arch/Sparc.cpp +++ b/clang/lib/Driver/ToolChains/Arch/Sparc.cpp @@ -130,7 +130,8 @@ std::string sparc::getSparcTargetCPU(const Driver &D, const ArgList &Args, return ""; } -void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args, +void sparc::getSparcTargetFeatures(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args, std::vector &Features) { sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args); if (FloatABI == sparc::FloatABI::Soft) @@ -150,11 +151,19 @@ void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args, Features.push_back("-popc"); } + // Those OSes default to enabling VIS on 64-bit SPARC. + // See also the corresponding code for external assemblers in + // sparc::getSparcAsmModeForCPU(). + bool IsSparcV9ATarget = + (Triple.getArch() == llvm::Triple::sparcv9) && + (Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD()); if (Arg *A = Args.getLastArg(options::OPT_mvis, options::OPT_mno_vis)) { if (A->getOption().matches(options::OPT_mvis)) Features.push_back("+vis"); else Features.push_back("-vis"); + } else if (IsSparcV9ATarget) { + Features.push_back("+vis"); } if (Arg *A = Args.getLastArg(options::OPT_mvis2, options::OPT_mno_vis2)) { diff --git a/clang/lib/Driver/ToolChains/Arch/Sparc.h b/clang/lib/Driver/ToolChains/Arch/Sparc.h index 2b178d9df1ee3..fa25b4992cc8b 100644 --- a/clang/lib/Driver/ToolChains/Arch/Sparc.h +++ b/clang/lib/Driver/ToolChains/Arch/Sparc.h @@ -31,7 +31,8 @@ FloatABI getSparcFloatABI(const Driver &D, const llvm::opt::ArgList &Args); std::string getSparcTargetCPU(const Driver &D, const llvm::opt::ArgList &Args, const llvm::Triple &Triple); -void getSparcTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args, +void getSparcTargetFeatures(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args, std::vector &Features); const char *getSparcAsmModeForCPU(llvm::StringRef Name, const llvm::Triple &Triple); diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp index e670696cd59ae..497f3330237b9 100644 --- a/clang/lib/Driver/ToolChains/BareMetal.cpp +++ b/clang/lib/Driver/ToolChains/BareMetal.cpp @@ -694,9 +694,6 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA, NeedCRTs) CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath(CRTEnd))); - if (TC.getTriple().isRISCV()) - CmdArgs.push_back("-X"); - // The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf // and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and // arm*-*-*bsd). diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 456bfe885f354..7d0c142ecd061 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -97,32 +97,15 @@ forAllAssociatedToolChains(Compilation &C, const JobAction &JA, // Apply Work on all the offloading tool chains associated with the current // action. - if (JA.isHostOffloading(Action::OFK_Cuda)) - Work(*C.getSingleOffloadToolChain()); - else if (JA.isDeviceOffloading(Action::OFK_Cuda)) - Work(*C.getSingleOffloadToolChain()); - else if (JA.isHostOffloading(Action::OFK_HIP)) - Work(*C.getSingleOffloadToolChain()); - else if (JA.isDeviceOffloading(Action::OFK_HIP)) - Work(*C.getSingleOffloadToolChain()); - - if (JA.isHostOffloading(Action::OFK_OpenMP)) { - auto TCs = C.getOffloadToolChains(); - for (auto II = TCs.first, IE = TCs.second; II != IE; ++II) - Work(*II->second); - } else if (JA.isDeviceOffloading(Action::OFK_OpenMP)) - Work(*C.getSingleOffloadToolChain()); - - if (JA.isHostOffloading(Action::OFK_SYCL)) { - auto TCs = C.getOffloadToolChains(); - for (auto II = TCs.first, IE = TCs.second; II != IE; ++II) - Work(*II->second); - } else if (JA.isDeviceOffloading(Action::OFK_SYCL)) - Work(*C.getSingleOffloadToolChain()); - - // - // TODO: Add support for other offloading programming models here. - // + for (Action::OffloadKind Kind : {Action::OFK_Cuda, Action::OFK_OpenMP, + Action::OFK_HIP, Action::OFK_SYCL}) { + if (JA.isHostOffloading(Kind)) { + auto TCs = C.getOffloadToolChains(Kind); + for (auto II = TCs.first, IE = TCs.second; II != IE; ++II) + Work(*II->second); + } else if (JA.isDeviceOffloading(Kind)) + Work(*C.getSingleOffloadToolChain()); + } } static bool @@ -2731,16 +2714,6 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, CmdArgs.push_back(MipsTargetFeature); } - // Those OSes default to enabling VIS on 64-bit SPARC. - // See also the corresponding code for external assemblers in - // sparc::getSparcAsmModeForCPU(). - bool IsSparcV9ATarget = - (C.getDefaultToolChain().getArch() == llvm::Triple::sparcv9) && - (Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD()); - if (IsSparcV9ATarget && SparcTargetFeatures.empty()) { - CmdArgs.push_back("-target-feature"); - CmdArgs.push_back("+vis"); - } for (const char *Feature : SparcTargetFeatures) { CmdArgs.push_back("-target-feature"); CmdArgs.push_back(Feature); @@ -3846,15 +3819,6 @@ static void RenderOpenACCOptions(const Driver &D, const ArgList &Args, return; CmdArgs.push_back("-fopenacc"); - - if (Arg *A = Args.getLastArg(options::OPT_openacc_macro_override)) { - StringRef Value = A->getValue(); - int Version; - if (!Value.getAsInteger(10, Version)) - A->renderAsInput(Args, CmdArgs); - else - D.Diag(diag::err_drv_clang_unsupported) << Value; - } } static void RenderBuiltinOptions(const ToolChain &TC, const llvm::Triple &T, @@ -4104,31 +4068,34 @@ static bool RenderModulesOptions(Compilation &C, const Driver &D, // module fragment. CmdArgs.push_back("-fskip-odr-check-in-gmf"); - if (Args.hasArg(options::OPT_modules_reduced_bmi) && + if (!Args.hasArg(options::OPT_fno_modules_reduced_bmi) && (Input.getType() == driver::types::TY_CXXModule || - Input.getType() == driver::types::TY_PP_CXXModule)) { + Input.getType() == driver::types::TY_PP_CXXModule) && + !Args.hasArg(options::OPT__precompile)) { CmdArgs.push_back("-fmodules-reduced-bmi"); if (Args.hasArg(options::OPT_fmodule_output_EQ)) Args.AddLastArg(CmdArgs, options::OPT_fmodule_output_EQ); - else { - if (Args.hasArg(options::OPT__precompile) && - (!Args.hasArg(options::OPT_o) || - Args.getLastArg(options::OPT_o)->getValue() == - getCXX20NamedModuleOutputPath(Args, Input.getBaseInput()))) { - D.Diag(diag::err_drv_reduced_module_output_overrided); - } - + else CmdArgs.push_back(Args.MakeArgString( "-fmodule-output=" + getCXX20NamedModuleOutputPath(Args, Input.getBaseInput()))); - } } - // Noop if we see '-fmodules-reduced-bmi' with other translation - // units than module units. This is more user friendly to allow end uers to - // enable this feature without asking for help from build systems. - Args.ClaimAllArgs(options::OPT_modules_reduced_bmi); + if (Args.hasArg(options::OPT_fmodules_reduced_bmi) && + Args.hasArg(options::OPT__precompile) && + (!Args.hasArg(options::OPT_o) || + Args.getLastArg(options::OPT_o)->getValue() == + getCXX20NamedModuleOutputPath(Args, Input.getBaseInput()))) { + D.Diag(diag::err_drv_reduced_module_output_overrided); + } + + // Noop if we see '-fmodules-reduced-bmi' or `-fno-modules-reduced-bmi` with + // other translation units than module units. This is more user friendly to + // allow end uers to enable this feature without asking for help from build + // systems. + Args.ClaimAllArgs(options::OPT_fmodules_reduced_bmi); + Args.ClaimAllArgs(options::OPT_fno_modules_reduced_bmi); // We need to include the case the input file is a module file here. // Since the default compilation model for C++ module interface unit will @@ -5001,8 +4968,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, else { // Host-side compilation. NormalizedTriple = - (IsCuda ? C.getSingleOffloadToolChain() - : C.getSingleOffloadToolChain()) + (IsCuda ? C.getOffloadToolChains(Action::OFK_Cuda).first->second + : C.getOffloadToolChains(Action::OFK_HIP).first->second) ->getTriple() .normalize(); if (IsCuda) { diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 651a39c03bb54..826e2ea7eb06d 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -856,7 +856,7 @@ void tools::getTargetFeatures(const Driver &D, const llvm::Triple &Triple, case llvm::Triple::sparc: case llvm::Triple::sparcel: case llvm::Triple::sparcv9: - sparc::getSparcTargetFeatures(D, Args, Features); + sparc::getSparcTargetFeatures(D, Triple, Args, Features); break; case llvm::Triple::r600: case llvm::Triple::amdgcn: diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp index 2373d945ae509..7d803beb7aa3c 100644 --- a/clang/lib/Driver/ToolChains/Cuda.cpp +++ b/clang/lib/Driver/ToolChains/Cuda.cpp @@ -815,7 +815,7 @@ NVPTXToolChain::getSystemGPUArchs(const ArgList &Args) const { else Program = GetProgramPath("nvptx-arch"); - auto StdoutOrErr = executeToolChainProgram(Program); + auto StdoutOrErr = getDriver().executeProgram({Program}); if (!StdoutOrErr) return StdoutOrErr.takeError(); diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 1edb83f7255eb..7ab41e9b85a04 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -447,6 +447,7 @@ void Flang::addTargetOptions(const ArgList &Args, // Add the target features. switch (TC.getArch()) { default: + getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false); break; case llvm::Triple::aarch64: getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false); diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp index 79b1b6960da1f..8f589186af343 100644 --- a/clang/lib/Driver/ToolChains/OpenBSD.cpp +++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp @@ -161,7 +161,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (Nopie || Profiling) CmdArgs.push_back("-nopie"); - if (Triple.isRISCV64()) { + if (Triple.isLoongArch64() || Triple.isRISCV64()) { CmdArgs.push_back("-X"); if (Args.hasArg(options::OPT_mno_relax)) CmdArgs.push_back("--no-relax"); diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 791afc1a97575..51a6f6b779e77 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -220,8 +220,9 @@ DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS, break; case NestedNameSpecifier::Namespace: { - const NamespaceDecl *NS = NNS->getAsNamespace(); - if (NS->isAnonymousNamespace()) + const NamespaceBaseDecl *NS = NNS->getAsNamespace(); + if (const auto *Namespace = dyn_cast(NS); + Namespace && Namespace->isAnonymousNamespace()) return Fragments; SmallString<128> USR; index::generateUSRForDecl(NS, USR); @@ -230,16 +231,6 @@ DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS, break; } - case NestedNameSpecifier::NamespaceAlias: { - const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias(); - SmallString<128> USR; - index::generateUSRForDecl(Alias, USR); - Fragments.append(Alias->getName(), - DeclarationFragments::FragmentKind::Identifier, USR, - Alias); - break; - } - case NestedNameSpecifier::Global: // The global specifier `::` at the beginning. No stored value. break; diff --git a/clang/lib/Format/BreakableToken.cpp b/clang/lib/Format/BreakableToken.cpp index c36cb74bc4501..29db20067c361 100644 --- a/clang/lib/Format/BreakableToken.cpp +++ b/clang/lib/Format/BreakableToken.cpp @@ -25,7 +25,7 @@ namespace clang { namespace format { -static constexpr StringRef Blanks = " \t\v\f\r"; +static constexpr StringRef Blanks(" \t\v\f\r"); static StringRef getLineCommentIndentPrefix(StringRef Comment, const FormatStyle &Style) { @@ -513,7 +513,7 @@ BreakableBlockComment::BreakableBlockComment( Decoration = ""; } for (size_t i = 1, e = Content.size(); i < e && !Decoration.empty(); ++i) { - const StringRef &Text = Content[i]; + const StringRef Text(Content[i]); if (i + 1 == e) { // If the last line is empty, the closing "*/" will have a star. if (Text.empty()) diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 4010f7fbd25be..bf67f9e5fd241 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -560,6 +560,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { return true; } } else if (Current.is(TT_BinaryOperator) && Current.CanBreakBefore && + Current.getPrecedence() != prec::Assignment && CurrentState.BreakBeforeParameter) { return true; } diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 78c09be458f0a..62feb3db0ed5e 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -665,21 +665,25 @@ template <> struct MappingTraits { IO.enumCase(Value, "Never", FormatStyle::SortIncludesOptions({})); IO.enumCase(Value, "CaseInsensitive", FormatStyle::SortIncludesOptions({/*Enabled=*/true, - /*IgnoreCase=*/true})); + /*IgnoreCase=*/true, + /*IgnoreExtension=*/false})); IO.enumCase(Value, "CaseSensitive", FormatStyle::SortIncludesOptions({/*Enabled=*/true, - /*IgnoreCase=*/false})); + /*IgnoreCase=*/false, + /*IgnoreExtension=*/false})); // For backward compatibility. IO.enumCase(Value, "false", FormatStyle::SortIncludesOptions({})); IO.enumCase(Value, "true", FormatStyle::SortIncludesOptions({/*Enabled=*/true, - /*IgnoreCase=*/false})); + /*IgnoreCase=*/false, + /*IgnoreExtension=*/false})); } static void mapping(IO &IO, FormatStyle::SortIncludesOptions &Value) { IO.mapOptional("Enabled", Value.Enabled); IO.mapOptional("IgnoreCase", Value.IgnoreCase); + IO.mapOptional("IgnoreExtension", Value.IgnoreExtension); } }; @@ -1650,7 +1654,8 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave; LLVMStyle.ShortNamespaceLines = 1; LLVMStyle.SkipMacroDefinitionBody = false; - LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false}; + LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false, + /*IgnoreExtension=*/false}; LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before; LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric; LLVMStyle.SpaceAfterCStyleCast = false; @@ -3239,19 +3244,27 @@ static void sortCppIncludes(const FormatStyle &Style, SmallVector Indices = llvm::to_vector<16>(llvm::seq(0, Includes.size())); - if (Style.SortIncludes.Enabled && Style.SortIncludes.IgnoreCase) { + if (Style.SortIncludes.Enabled) { stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) { - const auto LHSFilenameLower = Includes[LHSI].Filename.lower(); - const auto RHSFilenameLower = Includes[RHSI].Filename.lower(); - return std::tie(Includes[LHSI].Priority, LHSFilenameLower, - Includes[LHSI].Filename) < - std::tie(Includes[RHSI].Priority, RHSFilenameLower, - Includes[RHSI].Filename); - }); - } else { - stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) { - return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) < - std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename); + SmallString<128> LHSStem, RHSStem; + if (Style.SortIncludes.IgnoreExtension) { + LHSStem = Includes[LHSI].Filename; + RHSStem = Includes[RHSI].Filename; + llvm::sys::path::replace_extension(LHSStem, ""); + llvm::sys::path::replace_extension(RHSStem, ""); + } + std::string LHSStemLower, RHSStemLower; + std::string LHSFilenameLower, RHSFilenameLower; + if (Style.SortIncludes.IgnoreCase) { + LHSStemLower = LHSStem.str().lower(); + RHSStemLower = RHSStem.str().lower(); + LHSFilenameLower = Includes[LHSI].Filename.lower(); + RHSFilenameLower = Includes[RHSI].Filename.lower(); + } + return std::tie(Includes[LHSI].Priority, LHSStemLower, LHSStem, + LHSFilenameLower, Includes[LHSI].Filename) < + std::tie(Includes[RHSI].Priority, RHSStemLower, RHSStem, + RHSFilenameLower, Includes[RHSI].Filename); }); } diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp index 49da3160daf50..3f4aa52a87d2e 100644 --- a/clang/lib/Format/FormatTokenLexer.cpp +++ b/clang/lib/Format/FormatTokenLexer.cpp @@ -1198,7 +1198,7 @@ void FormatTokenLexer::truncateToken(size_t NewLen) { /// Count the length of leading whitespace in a token. static size_t countLeadingWhitespace(StringRef Text) { // Basically counting the length matched by this regex. - // "^([\n\r\f\v \t]|(\\\\|\\?\\?/)[\n\r])+" + // "^([\n\r\f\v \t]|\\\\[\n\r])+" // Directly using the regex turned out to be slow. With the regex // version formatting all files in this directory took about 1.25 // seconds. This version took about 0.5 seconds. @@ -1222,13 +1222,6 @@ static size_t countLeadingWhitespace(StringRef Text) { break; // Splice found, consume it. Cur = Lookahead + 1; - } else if (Cur[0] == '?' && Cur[1] == '?' && Cur[2] == '/' && - (Cur[3] == '\n' || Cur[3] == '\r')) { - // Newlines can also be escaped by a '?' '?' '/' trigraph. By the way, the - // characters are quoted individually in this comment because if we write - // them together some compilers warn that we have a trigraph in the code. - assert(End - Cur >= 4); - Cur += 4; } else { break; } @@ -1300,22 +1293,16 @@ FormatToken *FormatTokenLexer::getNextToken() { Style.TabWidth - (Style.TabWidth ? Column % Style.TabWidth : 0); break; case '\\': - case '?': - case '/': - // The text was entirely whitespace when this loop was entered. Thus - // this has to be an escape sequence. - assert(Text.substr(i, 4) == "\?\?/\r" || - Text.substr(i, 4) == "\?\?/\n" || - (i >= 1 && (Text.substr(i - 1, 4) == "\?\?/\r" || - Text.substr(i - 1, 4) == "\?\?/\n")) || - (i >= 2 && (Text.substr(i - 2, 4) == "\?\?/\r" || - Text.substr(i - 2, 4) == "\?\?/\n")) || - (Text[i] == '\\' && [&]() -> bool { - size_t j = i + 1; - while (j < Text.size() && isHorizontalWhitespace(Text[j])) - ++j; - return j < Text.size() && (Text[j] == '\n' || Text[j] == '\r'); - }())); + // The code preceding the loop and in the countLeadingWhitespace + // function guarantees that Text is entirely whitespace, not including + // comments but including escaped newlines. So the character shows up, + // then it has to be in an escape sequence. + assert([&]() -> bool { + size_t j = i + 1; + while (j < Text.size() && isHorizontalWhitespace(Text[j])) + ++j; + return j < Text.size() && (Text[j] == '\n' || Text[j] == '\r'); + }()); InEscape = true; break; default: diff --git a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp index 87823ae32b113..80487fa673bf0 100644 --- a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp +++ b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp @@ -19,7 +19,7 @@ namespace format { enum class Base { Binary, Decimal, Hex, Other }; -static Base getBase(const StringRef IntegerLiteral) { +static Base getBase(StringRef IntegerLiteral) { assert(IntegerLiteral.size() > 1); if (IntegerLiteral[0] > '0') { @@ -164,8 +164,8 @@ IntegerLiteralSeparatorFixer::process(const Environment &Env, return {Result, 0}; } -bool IntegerLiteralSeparatorFixer::checkSeparator( - const StringRef IntegerLiteral, int DigitsPerGroup) const { +bool IntegerLiteralSeparatorFixer::checkSeparator(StringRef IntegerLiteral, + int DigitsPerGroup) const { assert(DigitsPerGroup > 0); int I = 0; @@ -184,7 +184,7 @@ bool IntegerLiteralSeparatorFixer::checkSeparator( return true; } -std::string IntegerLiteralSeparatorFixer::format(const StringRef IntegerLiteral, +std::string IntegerLiteralSeparatorFixer::format(StringRef IntegerLiteral, int DigitsPerGroup, int DigitCount, bool RemoveSeparator) const { diff --git a/clang/lib/Format/IntegerLiteralSeparatorFixer.h b/clang/lib/Format/IntegerLiteralSeparatorFixer.h index 2c158e4473bfe..e24af18bb9572 100644 --- a/clang/lib/Format/IntegerLiteralSeparatorFixer.h +++ b/clang/lib/Format/IntegerLiteralSeparatorFixer.h @@ -26,8 +26,8 @@ class IntegerLiteralSeparatorFixer { const FormatStyle &Style); private: - bool checkSeparator(const StringRef IntegerLiteral, int DigitsPerGroup) const; - std::string format(const StringRef IntegerLiteral, int DigitsPerGroup, + bool checkSeparator(StringRef IntegerLiteral, int DigitsPerGroup) const; + std::string format(StringRef IntegerLiteral, int DigitsPerGroup, int DigitCount, bool RemoveSeparator) const; char Separator; diff --git a/clang/lib/Format/ObjCPropertyAttributeOrderFixer.cpp b/clang/lib/Format/ObjCPropertyAttributeOrderFixer.cpp index 37a1807197341..b885942efcb55 100644 --- a/clang/lib/Format/ObjCPropertyAttributeOrderFixer.cpp +++ b/clang/lib/Format/ObjCPropertyAttributeOrderFixer.cpp @@ -66,7 +66,7 @@ void ObjCPropertyAttributeOrderFixer::sortPropertyAttributes( return; } - const StringRef Attribute{Tok->TokenText}; + const StringRef Attribute(Tok->TokenText); StringRef Value; // Also handle `getter=getFoo` attributes. diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 739209a5681f8..581bfbab0972d 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2996,14 +2996,18 @@ class AnnotatingParser { const FormatToken *PrevToken = Tok.getPreviousNonComment(); if (!PrevToken) return TT_UnaryOperator; - if (PrevToken->is(TT_TypeName)) + if (PrevToken->isTypeName(LangOpts)) return TT_PointerOrReference; if (PrevToken->isPlacementOperator() && Tok.is(tok::ampamp)) return TT_BinaryOperator; - const FormatToken *NextToken = Tok.getNextNonComment(); + auto *NextToken = Tok.getNextNonComment(); if (!NextToken) return TT_PointerOrReference; + if (NextToken->is(tok::greater)) { + NextToken->setFinalizedType(TT_TemplateCloser); + return TT_PointerOrReference; + } if (InTemplateArgument && NextToken->is(tok::kw_noexcept)) return TT_BinaryOperator; @@ -3112,7 +3116,7 @@ class AnnotatingParser { // It's more likely that & represents operator& than an uninitialized // reference. - if (Tok.is(tok::amp) && PrevToken && PrevToken->Tok.isAnyIdentifier() && + if (Tok.is(tok::amp) && PrevToken->Tok.isAnyIdentifier() && IsChainedOperatorAmpOrMember(PrevToken->getPreviousNonComment()) && NextToken && NextToken->Tok.isAnyIdentifier()) { if (auto NextNext = NextToken->getNextNonComment(); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 56d10ceb986b3..3a36250da57a3 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -593,11 +593,11 @@ static bool FixupInvocation(CompilerInvocation &Invocation, CodeGenOpts.CodeModel = TargetOpts.CodeModel; CodeGenOpts.LargeDataThreshold = TargetOpts.LargeDataThreshold; - if (LangOpts.getExceptionHandling() != - LangOptions::ExceptionHandlingKind::None && + if (CodeGenOpts.getExceptionHandling() != + CodeGenOptions::ExceptionHandlingKind::None && T.isWindowsMSVCEnvironment()) Diags.Report(diag::err_fe_invalid_exception_model) - << static_cast(LangOpts.getExceptionHandling()) << T.str(); + << static_cast(CodeGenOpts.getExceptionHandling()) << T.str(); if (LangOpts.AppleKext && !LangOpts.CPlusPlus) Diags.Report(diag::warn_c_kext); @@ -3713,23 +3713,6 @@ static StringRef GetInputKindName(InputKind IK) { llvm_unreachable("unknown input language"); } -static StringRef getExceptionHandlingName(unsigned EHK) { - switch (static_cast(EHK)) { - case LangOptions::ExceptionHandlingKind::None: - return "none"; - case LangOptions::ExceptionHandlingKind::DwarfCFI: - return "dwarf"; - case LangOptions::ExceptionHandlingKind::SjLj: - return "sjlj"; - case LangOptions::ExceptionHandlingKind::WinEH: - return "seh"; - case LangOptions::ExceptionHandlingKind::Wasm: - return "wasm"; - } - - llvm_unreachable("covered switch"); -} - void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts, ArgumentConsumer Consumer, const llvm::Triple &T, @@ -3745,10 +3728,6 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts, GenerateArg(Consumer, OPT_pic_is_pie); for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize)) GenerateArg(Consumer, OPT_fsanitize_EQ, Sanitizer); - if (Opts.ExceptionHandling) { - GenerateArg(Consumer, OPT_exception_model, - getExceptionHandlingName(Opts.ExceptionHandling)); - } return; } @@ -3934,12 +3913,8 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts, if (Opts.OpenMPCUDAMode) GenerateArg(Consumer, OPT_fopenmp_cuda_mode); - if (Opts.OpenACC) { + if (Opts.OpenACC) GenerateArg(Consumer, OPT_fopenacc); - if (!Opts.OpenACCMacroOverride.empty()) - GenerateArg(Consumer, OPT_openacc_macro_override, - Opts.OpenACCMacroOverride); - } // The arguments used to set Optimize, OptimizeSize and NoInlineDefine are // generated from CodeGenOptions. @@ -4057,24 +4032,6 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ), Diags, Opts.Sanitize); - if (const Arg *A = Args.getLastArg(options::OPT_exception_model)) { - std::optional EMValue = - llvm::StringSwitch>( - A->getValue()) - .Case("dwarf", LangOptions::ExceptionHandlingKind::DwarfCFI) - .Case("sjlj", LangOptions::ExceptionHandlingKind::SjLj) - .Case("seh", LangOptions::ExceptionHandlingKind::WinEH) - .Case("wasm", LangOptions::ExceptionHandlingKind::Wasm) - .Case("none", LangOptions::ExceptionHandlingKind::None) - .Default(std::nullopt); - if (EMValue) { - Opts.ExceptionHandling = static_cast(*EMValue); - } else { - Diags.Report(diag::err_drv_invalid_value) - << A->getAsString(Args) << A->getValue(); - } - } - return Diags.getNumErrors() == NumErrorsBefore; } @@ -4463,13 +4420,9 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Args.hasArg(options::OPT_fopenmp_cuda_mode); // OpenACC Configuration. - if (Args.hasArg(options::OPT_fopenacc)) { + if (Args.hasArg(options::OPT_fopenacc)) Opts.OpenACC = true; - if (Arg *A = Args.getLastArg(options::OPT_openacc_macro_override)) - Opts.OpenACCMacroOverride = A->getValue(); - } - if (Arg *A = Args.getLastArg(OPT_ffp_contract)) { StringRef Val = A->getValue(); if (Val == "fast") diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 136bc55847cc1..382ccd610946c 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -639,16 +639,8 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, } } - if (LangOpts.OpenACC) { - // FIXME: When we have full support for OpenACC, we should set this to the - // version we support. Until then, set as '1' by default, but provide a - // temporary mechanism for users to override this so real-world examples can - // be tested against. - if (!LangOpts.OpenACCMacroOverride.empty()) - Builder.defineMacro("_OPENACC", LangOpts.OpenACCMacroOverride); - else - Builder.defineMacro("_OPENACC", "1"); - } + if (LangOpts.OpenACC) + Builder.defineMacro("_OPENACC", "202506"); } /// Initialize the predefined C++ language feature test macros defined in @@ -1032,14 +1024,14 @@ static void InitializePredefinedMacros(const TargetInfo &TI, if (LangOpts.GNUCVersion && LangOpts.RTTI) Builder.defineMacro("__GXX_RTTI"); - if (LangOpts.hasSjLjExceptions()) + if (CGOpts.hasSjLjExceptions()) Builder.defineMacro("__USING_SJLJ_EXCEPTIONS__"); - else if (LangOpts.hasSEHExceptions()) + else if (CGOpts.hasSEHExceptions()) Builder.defineMacro("__SEH__"); - else if (LangOpts.hasDWARFExceptions() && + else if (CGOpts.hasDWARFExceptions() && (TI.getTriple().isThumb() || TI.getTriple().isARM())) Builder.defineMacro("__ARM_DWARF_EH__"); - else if (LangOpts.hasWasmExceptions() && TI.getTriple().isWasm()) + else if (CGOpts.hasWasmExceptions() && TI.getTriple().isWasm()) Builder.defineMacro("__WASM_EXCEPTIONS__"); if (LangOpts.Deprecated) diff --git a/clang/lib/Headers/__clang_spirv_builtins.h b/clang/lib/Headers/__clang_spirv_builtins.h index 9915cdfcae7cd..9c7215f506508 100644 --- a/clang/lib/Headers/__clang_spirv_builtins.h +++ b/clang/lib/Headers/__clang_spirv_builtins.h @@ -52,30 +52,30 @@ // Builtin IDs and sizes extern __SPIRV_BUILTIN_ALIAS(__builtin_spirv_num_workgroups) __size_t - __spirv_NumWorkgroups(int); + __spirv_BuiltInNumWorkgroups(int); extern __SPIRV_BUILTIN_ALIAS(__builtin_spirv_workgroup_size) __size_t - __spirv_WorkgroupSize(int); + __spirv_BuiltInWorkgroupSize(int); extern __SPIRV_BUILTIN_ALIAS(__builtin_spirv_workgroup_id) __size_t - __spirv_WorkgroupId(int); + __spirv_BuiltInWorkgroupId(int); extern __SPIRV_BUILTIN_ALIAS(__builtin_spirv_local_invocation_id) __size_t - __spirv_LocalInvocationId(int); + __spirv_BuiltInLocalInvocationId(int); extern __SPIRV_BUILTIN_ALIAS(__builtin_spirv_global_invocation_id) __size_t - __spirv_GlobalInvocationId(int); + __spirv_BuiltInGlobalInvocationId(int); extern __SPIRV_BUILTIN_ALIAS(__builtin_spirv_global_size) __size_t - __spirv_GlobalSize(int); + __spirv_BuiltInGlobalSize(int); extern __SPIRV_BUILTIN_ALIAS(__builtin_spirv_global_offset) __size_t - __spirv_GlobalOffset(int); + __spirv_BuiltInGlobalOffset(int); extern __SPIRV_BUILTIN_ALIAS(__builtin_spirv_subgroup_size) __uint32_t - __spirv_SubgroupSize(); + __spirv_BuiltInSubgroupSize(); extern __SPIRV_BUILTIN_ALIAS(__builtin_spirv_subgroup_max_size) __uint32_t - __spirv_SubgroupMaxSize(); + __spirv_BuiltInSubgroupMaxSize(); extern __SPIRV_BUILTIN_ALIAS(__builtin_spirv_num_subgroups) __uint32_t - __spirv_NumSubgroups(); + __spirv_BuiltInNumSubgroups(); extern __SPIRV_BUILTIN_ALIAS(__builtin_spirv_subgroup_id) __uint32_t - __spirv_SubgroupId(); + __spirv_BuiltInSubgroupId(); extern __SPIRV_BUILTIN_ALIAS(__builtin_spirv_subgroup_local_invocation_id) - __uint32_t __spirv_SubgroupLocalInvocationId(); + __uint32_t __spirv_BuiltInSubgroupLocalInvocationId(); // OpGenericCastToPtrExplicit diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h index 4eb7b8f45c85a..e8ccccb489815 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h @@ -71,6 +71,16 @@ constexpr vector reflect_vec_impl(vector I, vector N) { #endif } +template constexpr T refract_impl(T I, T N, U Eta) { +#if (__has_builtin(__builtin_spirv_refract)) + return __builtin_spirv_refract(I, N, Eta); +#endif + T Mul = dot(N, I); + T K = 1 - Eta * Eta * (1 - Mul * Mul); + T Result = (Eta * I - (Eta * Mul + sqrt(K)) * N); + return select(K < 0, static_cast(0), Result); +} + template constexpr T fmod_impl(T X, T Y) { #if !defined(__DIRECTX__) return __builtin_elementwise_fmod(X, Y); diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index ea880105fac3b..499a05328ee4f 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -475,6 +475,65 @@ reflect(__detail::HLSL_FIXED_VECTOR I, return __detail::reflect_vec_impl(I, N); } +//===----------------------------------------------------------------------===// +// refract builtin +//===----------------------------------------------------------------------===// + +/// \fn T refract(T I, T N, T eta) +/// \brief Returns a refraction using an entering ray, \a I, a surface +/// normal, \a N and refraction index \a eta +/// \param I The entering ray. +/// \param N The surface normal. +/// \param eta The refraction index. +/// +/// The return value is a floating-point vector that represents the refraction +/// using the refraction index, \a eta, for the direction of the entering ray, +/// \a I, off a surface with the normal \a N. +/// +/// This function calculates the refraction vector using the following formulas: +/// k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)) +/// if k < 0.0 the result is 0.0 +/// otherwise, the result is eta * I - (eta * dot(N, I) + sqrt(k)) * N +/// +/// I and N must already be normalized in order to achieve the desired result. +/// +/// I and N must be a scalar or vector whose component type is +/// floating-point. +/// +/// eta must be a 16-bit or 32-bit floating-point scalar. +/// +/// Result type, the type of I, and the type of N must all be the same type. + +template +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +const inline __detail::enable_if_t<__detail::is_arithmetic::Value && + __detail::is_same::value, + T> refract(T I, T N, T eta) { + return __detail::refract_impl(I, N, eta); +} + +template +const inline __detail::enable_if_t< + __detail::is_arithmetic::Value && __detail::is_same::value, T> +refract(T I, T N, T eta) { + return __detail::refract_impl(I, N, eta); +} + +template +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +const inline __detail::HLSL_FIXED_VECTOR refract( + __detail::HLSL_FIXED_VECTOR I, + __detail::HLSL_FIXED_VECTOR N, half eta) { + return __detail::refract_impl(I, N, eta); +} + +template +const inline __detail::HLSL_FIXED_VECTOR +refract(__detail::HLSL_FIXED_VECTOR I, + __detail::HLSL_FIXED_VECTOR N, float eta) { + return __detail::refract_impl(I, N, eta); +} + //===----------------------------------------------------------------------===// // smoothstep builtin //===----------------------------------------------------------------------===// diff --git a/clang/lib/Index/IndexTypeSourceInfo.cpp b/clang/lib/Index/IndexTypeSourceInfo.cpp index 98b5513128fbe..adc33b3abd822 100644 --- a/clang/lib/Index/IndexTypeSourceInfo.cpp +++ b/clang/lib/Index/IndexTypeSourceInfo.cpp @@ -271,10 +271,6 @@ void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(), Loc, Parent, DC, SymbolRoleSet()); break; - case NestedNameSpecifier::NamespaceAlias: - handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(), - Loc, Parent, DC, SymbolRoleSet()); - break; case NestedNameSpecifier::TypeSpec: indexTypeLoc(NNS.getTypeLoc(), Parent, DC); diff --git a/clang/lib/Interpreter/CMakeLists.txt b/clang/lib/Interpreter/CMakeLists.txt index 38cf139fa86a6..70de4a2aaa541 100644 --- a/clang/lib/Interpreter/CMakeLists.txt +++ b/clang/lib/Interpreter/CMakeLists.txt @@ -29,6 +29,7 @@ add_clang_library(clangInterpreter InterpreterUtils.cpp RemoteJITUtils.cpp Value.cpp + InterpreterValuePrinter.cpp ${WASM_SRC} PARTIAL_SOURCES_INTENDED diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index ed3bae59a144c..db6a2bb914f43 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -264,7 +264,7 @@ class InProcessPrintingASTConsumer final : public MultiplexConsumer { if (auto *TLSD = llvm::dyn_cast(D)) if (TLSD && TLSD->isSemiMissing()) { auto ExprOrErr = - Interp.ExtractValueFromExpr(cast(TLSD->getStmt())); + Interp.convertExprToValue(cast(TLSD->getStmt())); if (llvm::Error E = ExprOrErr.takeError()) { llvm::logAllUnhandledErrors(std::move(E), llvm::errs(), "Value printing failed: "); @@ -440,11 +440,10 @@ const char *const Runtimes = R"( #define __CLANG_REPL__ 1 #ifdef __cplusplus #define EXTERN_C extern "C" - void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*); struct __clang_Interpreter_NewTag{} __ci_newtag; void* operator new(__SIZE_TYPE__, void* __p, __clang_Interpreter_NewTag) noexcept; template - void __clang_Interpreter_SetValueCopyArr(T* Src, void* Placement, unsigned long Size) { + void __clang_Interpreter_SetValueCopyArr(const T* Src, void* Placement, unsigned long Size) { for (auto Idx = 0; Idx < Size; ++Idx) new ((void*)(((T*)Placement) + Idx), __ci_newtag) T(Src[Idx]); } @@ -454,8 +453,12 @@ const char *const Runtimes = R"( } #else #define EXTERN_C extern + EXTERN_C void *memcpy(void *restrict dst, const void *restrict src, __SIZE_TYPE__ n); + EXTERN_C inline void __clang_Interpreter_SetValueCopyArr(const void* Src, void* Placement, unsigned long Size) { + memcpy(Placement, Src, Size); + } #endif // __cplusplus - + EXTERN_C void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*); EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...); )"; @@ -470,12 +473,12 @@ Interpreter::create(std::unique_ptr CI, // Add runtime code and set a marker to hide it from user code. Undo will not // go through that. - auto PTU = Interp->Parse(Runtimes); - if (!PTU) - return PTU.takeError(); + Err = Interp->ParseAndExecute(Runtimes); + if (Err) + return std::move(Err); + Interp->markUserCodeStart(); - Interp->ValuePrintingInfo.resize(4); return std::move(Interp); } @@ -524,12 +527,11 @@ Interpreter::createWithCUDA(std::unique_ptr CI, return std::move(Interp); } +CompilerInstance *Interpreter::getCompilerInstance() { return CI.get(); } const CompilerInstance *Interpreter::getCompilerInstance() const { - return CI.get(); + return const_cast(this)->getCompilerInstance(); } -CompilerInstance *Interpreter::getCompilerInstance() { return CI.get(); } - llvm::Expected Interpreter::getExecutionEngine() { if (!IncrExecutor) { if (auto Err = CreateExecutor()) @@ -610,7 +612,14 @@ Interpreter::Parse(llvm::StringRef Code) { if (!TuOrErr) return TuOrErr.takeError(); - return RegisterPTU(*TuOrErr); + PTUs.emplace_back(PartialTranslationUnit()); + PartialTranslationUnit &LastPTU = PTUs.back(); + LastPTU.TUPart = *TuOrErr; + + if (std::unique_ptr M = GenModule()) + LastPTU.TheModule = std::move(M); + + return LastPTU; } static llvm::Expected @@ -808,10 +817,10 @@ Interpreter::GenModule(IncrementalAction *Action) { // sure it always stays empty. assert(((!CachedInCodeGenModule || !getCompilerInstance()->getPreprocessorOpts().Includes.empty()) || - (CachedInCodeGenModule->empty() && - CachedInCodeGenModule->global_empty() && - CachedInCodeGenModule->alias_empty() && - CachedInCodeGenModule->ifunc_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()); @@ -828,4 +837,4 @@ CodeGenerator *Interpreter::getCodeGen(IncrementalAction *Action) const { return nullptr; return static_cast(WrappedAct)->getCodeGenerator(); } -} // namespace clang +} // end namespace clang diff --git a/clang/lib/Interpreter/InterpreterUtils.cpp b/clang/lib/Interpreter/InterpreterUtils.cpp index 45f6322b8461e..a19f96c80b94f 100644 --- a/clang/lib/Interpreter/InterpreterUtils.cpp +++ b/clang/lib/Interpreter/InterpreterUtils.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "InterpreterUtils.h" +#include "clang/AST/QualTypeNames.h" namespace clang { @@ -81,7 +82,7 @@ NamedDecl *LookupNamed(Sema &S, llvm::StringRef Name, else { const DeclContext *PrimaryWithin = nullptr; if (const auto *TD = dyn_cast(Within)) - PrimaryWithin = llvm::dyn_cast_or_null(TD->getDefinition()); + PrimaryWithin = dyn_cast_if_present(TD->getDefinition()); else PrimaryWithin = Within->getPrimaryContext(); @@ -97,15 +98,16 @@ NamedDecl *LookupNamed(Sema &S, llvm::StringRef Name, R.resolveKind(); if (R.isSingleResult()) - return llvm::dyn_cast(R.getFoundDecl()); + return dyn_cast(R.getFoundDecl()); return nullptr; } std::string GetFullTypeName(ASTContext &Ctx, QualType QT) { + QualType FQT = TypeName::getFullyQualifiedType(QT, Ctx); PrintingPolicy Policy(Ctx.getPrintingPolicy()); Policy.SuppressScope = false; Policy.AnonymousTagLocations = false; - return QT.getAsString(Policy); + return FQT.getAsString(Policy); } } // namespace clang diff --git a/clang/lib/Interpreter/InterpreterUtils.h b/clang/lib/Interpreter/InterpreterUtils.h index c7b405b486d93..fbf9814b0d4a7 100644 --- a/clang/lib/Interpreter/InterpreterUtils.h +++ b/clang/lib/Interpreter/InterpreterUtils.h @@ -45,7 +45,7 @@ NamespaceDecl *LookupNamespace(Sema &S, llvm::StringRef Name, const DeclContext *Within = nullptr); NamedDecl *LookupNamed(Sema &S, llvm::StringRef Name, - const DeclContext *Within); + const DeclContext *Within = nullptr); std::string GetFullTypeName(ASTContext &Ctx, QualType QT); } // namespace clang diff --git a/clang/lib/Interpreter/InterpreterValuePrinter.cpp b/clang/lib/Interpreter/InterpreterValuePrinter.cpp index 3e7e32b2e8557..0ea6274b79cba 100644 --- a/clang/lib/Interpreter/InterpreterValuePrinter.cpp +++ b/clang/lib/Interpreter/InterpreterValuePrinter.cpp @@ -18,6 +18,7 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Interpreter/Interpreter.h" #include "clang/Interpreter/Value.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Sema.h" @@ -25,13 +26,335 @@ #include "llvm/Support/raw_ostream.h" #include - +#include #include +#include +#include + +#define DEBUG_TYPE "interp-value" + +using namespace clang; + +static std::string DeclTypeToString(const QualType &QT, NamedDecl *D) { + std::string Str; + llvm::raw_string_ostream SS(Str); + if (QT.hasQualifiers()) + SS << QT.getQualifiers().getAsString() << " "; + SS << D->getQualifiedNameAsString(); + return Str; +} + +static std::string QualTypeToString(ASTContext &Ctx, QualType QT) { + PrintingPolicy Policy(Ctx.getPrintingPolicy()); + // Print the Allocator in STL containers, for instance. + Policy.SuppressDefaultTemplateArgs = false; + Policy.SuppressUnwrittenScope = true; + // Print 'a >' rather than 'a>'. + Policy.SplitTemplateClosers = true; + + struct LocalPrintingPolicyRAII { + ASTContext &Context; + PrintingPolicy Policy; + + LocalPrintingPolicyRAII(ASTContext &Ctx, PrintingPolicy &PP) + : Context(Ctx), Policy(Ctx.getPrintingPolicy()) { + Context.setPrintingPolicy(PP); + } + ~LocalPrintingPolicyRAII() { Context.setPrintingPolicy(Policy); } + } X(Ctx, Policy); + + const QualType NonRefTy = QT.getNonReferenceType(); + + if (const auto *TTy = llvm::dyn_cast(NonRefTy)) + return DeclTypeToString(NonRefTy, TTy->getDecl()); + + if (const auto *TRy = dyn_cast(NonRefTy)) + return DeclTypeToString(NonRefTy, TRy->getDecl()); + + const QualType Canon = NonRefTy.getCanonicalType(); + + // FIXME: How a builtin type can be a function pointer type? + if (Canon->isBuiltinType() && !NonRefTy->isFunctionPointerType() && + !NonRefTy->isMemberPointerType()) + return Canon.getAsString(Ctx.getPrintingPolicy()); + + if (const auto *TDTy = dyn_cast(NonRefTy)) { + // FIXME: TemplateSpecializationType & SubstTemplateTypeParmType checks + // are predominately to get STL containers to print nicer and might be + // better handled in GetFullyQualifiedName. + // + // std::vector::iterator is a TemplateSpecializationType + // std::vector::value_type is a SubstTemplateTypeParmType + // + QualType SSDesugar = TDTy->getLocallyUnqualifiedSingleStepDesugaredType(); + if (llvm::isa(SSDesugar)) + return GetFullTypeName(Ctx, Canon); + else if (llvm::isa(SSDesugar)) + return GetFullTypeName(Ctx, NonRefTy); + return DeclTypeToString(NonRefTy, TDTy->getDecl()); + } + return GetFullTypeName(Ctx, NonRefTy); +} + +static std::string EnumToString(const Value &V) { + std::string Str; + llvm::raw_string_ostream SS(Str); + ASTContext &Ctx = const_cast(V.getASTContext()); + + QualType DesugaredTy = V.getType().getDesugaredType(Ctx); + const EnumType *EnumTy = DesugaredTy.getNonReferenceType()->getAs(); + assert(EnumTy && "Fail to cast to enum type"); + + EnumDecl *ED = EnumTy->getDecl(); + uint64_t Data = V.convertTo(); + bool IsFirst = true; + llvm::APSInt AP = Ctx.MakeIntValue(Data, DesugaredTy); + + for (auto I = ED->enumerator_begin(), E = ED->enumerator_end(); I != E; ++I) { + if (I->getInitVal() == AP) { + if (!IsFirst) + SS << " ? "; + SS << "(" + I->getQualifiedNameAsString() << ")"; + IsFirst = false; + } + } + llvm::SmallString<64> APStr; + AP.toString(APStr, /*Radix=*/10); + SS << " : " << QualTypeToString(Ctx, ED->getIntegerType()) << " " << APStr; + return Str; +} + +static std::string FunctionToString(const Value &V, const void *Ptr) { + std::string Str; + llvm::raw_string_ostream SS(Str); + SS << "Function @" << Ptr; + + const DeclContext *PTU = V.getASTContext().getTranslationUnitDecl(); + // Find the last top-level-stmt-decl. This is a forward iterator but the + // partial translation unit should not be large. + const TopLevelStmtDecl *TLSD = nullptr; + for (const Decl *D : PTU->noload_decls()) + if (isa(D)) + TLSD = cast(D); + + // Get __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void + // *OpaqueType, void *Val); + const FunctionDecl *FD = nullptr; + if (auto *InterfaceCall = llvm::dyn_cast(TLSD->getStmt())) { + const auto *Arg = InterfaceCall->getArg(/*Val*/ 3); + // Get rid of cast nodes. + while (const CastExpr *CastE = llvm::dyn_cast(Arg)) + Arg = CastE->getSubExpr(); + if (const DeclRefExpr *DeclRefExp = llvm::dyn_cast(Arg)) + FD = llvm::dyn_cast(DeclRefExp->getDecl()); + + if (FD) { + SS << '\n'; + const clang::FunctionDecl *FDef; + if (FD->hasBody(FDef)) + FDef->print(SS); + } + } + return Str; +} + +static std::string VoidPtrToString(const void *Ptr) { + std::string Str; + llvm::raw_string_ostream SS(Str); + SS << Ptr; + return Str; +} + +static std::string CharPtrToString(const char *Ptr) { + if (!Ptr) + return "0"; + + std::string Result = "\""; + Result += Ptr; + Result += '"'; + return Result; +} namespace clang { +struct ValueRef : public Value { + ValueRef(const Interpreter *In, void *Ty) : Value(In, Ty) { + // Tell the base class to not try to deallocate if it manages the value. + IsManuallyAlloc = false; + } +}; + +std::string Interpreter::ValueDataToString(const Value &V) const { + Sema &S = getCompilerInstance()->getSema(); + ASTContext &Ctx = S.getASTContext(); + + QualType QT = V.getType(); + + if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(QT)) { + QualType ElemTy = CAT->getElementType(); + size_t ElemCount = Ctx.getConstantArrayElementCount(CAT); + const Type *BaseTy = CAT->getBaseElementTypeUnsafe(); + size_t ElemSize = Ctx.getTypeSizeInChars(BaseTy).getQuantity(); + + // Treat null terminated char arrays as strings basically. + if (ElemTy->isCharType()) { + char last = *(char *)(((uintptr_t)V.getPtr()) + ElemCount * ElemSize - 1); + if (last == '\0') + return CharPtrToString((char *)V.getPtr()); + } + + std::string Result = "{ "; + for (unsigned Idx = 0, N = CAT->getZExtSize(); Idx < N; ++Idx) { + ValueRef InnerV = ValueRef(this, ElemTy.getAsOpaquePtr()); + if (ElemTy->isBuiltinType()) { + // Single dim arrays, advancing. + uintptr_t Offset = (uintptr_t)V.getPtr() + Idx * ElemSize; + InnerV.setRawBits((void *)Offset, ElemSize * 8); + } else { + // Multi dim arrays, position to the next dimension. + size_t Stride = ElemCount / N; + uintptr_t Offset = ((uintptr_t)V.getPtr()) + Idx * Stride * ElemSize; + InnerV.setPtr((void *)Offset); + } + + Result += ValueDataToString(InnerV); + + // Skip the \0 if the char types + if (Idx < N - 1) + Result += ", "; + } + Result += " }"; + return Result; + } + + QualType DesugaredTy = QT.getDesugaredType(Ctx); + QualType NonRefTy = DesugaredTy.getNonReferenceType(); + + // FIXME: Add support for user defined printers. + // LookupResult R = LookupUserDefined(S, QT); + // if (!R.empty()) + // return CallUserSpecifiedPrinter(R, V); + + // If it is a builtin type dispatch to the builtin overloads. + if (auto *BT = DesugaredTy.getCanonicalType()->getAs()) { + + auto formatFloating = [](auto Val, char Suffix = '\0') -> std::string { + std::string Out; + llvm::raw_string_ostream SS(Out); + + if (std::isnan(Val) || std::isinf(Val)) { + SS << llvm::format("%g", Val); + return SS.str(); + } + if (Val == static_cast(static_cast(Val))) + SS << llvm::format("%.1f", Val); + else if (std::abs(Val) < 1e-4 || std::abs(Val) > 1e6 || Suffix == 'f') + SS << llvm::format("%#.6g", Val); + else if (Suffix == 'L') + SS << llvm::format("%#.12Lg", Val); + else + SS << llvm::format("%#.8g", Val); + + if (Suffix != '\0') + SS << Suffix; + return SS.str(); + }; + + std::string Str; + llvm::raw_string_ostream SS(Str); + switch (BT->getKind()) { + default: + return "{ error: unknown builtin type '" + std::to_string(BT->getKind()) + + " '}"; + case clang::BuiltinType::Bool: + SS << ((V.getBool()) ? "true" : "false"); + return Str; + case clang::BuiltinType::Char_S: + SS << '\'' << V.getChar_S() << '\''; + return Str; + case clang::BuiltinType::SChar: + SS << '\'' << V.getSChar() << '\''; + return Str; + case clang::BuiltinType::Char_U: + SS << '\'' << V.getChar_U() << '\''; + return Str; + case clang::BuiltinType::UChar: + SS << '\'' << V.getUChar() << '\''; + return Str; + case clang::BuiltinType::Short: + SS << V.getShort(); + return Str; + case clang::BuiltinType::UShort: + SS << V.getUShort(); + return Str; + case clang::BuiltinType::Int: + SS << V.getInt(); + return Str; + case clang::BuiltinType::UInt: + SS << V.getUInt(); + return Str; + case clang::BuiltinType::Long: + SS << V.getLong(); + return Str; + case clang::BuiltinType::ULong: + SS << V.getULong(); + return Str; + case clang::BuiltinType::LongLong: + SS << V.getLongLong(); + return Str; + case clang::BuiltinType::ULongLong: + SS << V.getULongLong(); + return Str; + case clang::BuiltinType::Float: + return formatFloating(V.getFloat(), /*suffix=*/'f'); + + case clang::BuiltinType::Double: + return formatFloating(V.getDouble()); + + case clang::BuiltinType::LongDouble: + return formatFloating(V.getLongDouble(), /*suffix=*/'L'); + } + } + + if ((NonRefTy->isPointerType() || NonRefTy->isMemberPointerType()) && + NonRefTy->getPointeeType()->isFunctionProtoType()) + return FunctionToString(V, V.getPtr()); + + if (NonRefTy->isFunctionType()) + return FunctionToString(V, &V); + + if (NonRefTy->isEnumeralType()) + return EnumToString(V); + + if (NonRefTy->isNullPtrType()) + return "nullptr\n"; + + // FIXME: Add support for custom printers in C. + if (NonRefTy->isPointerType()) { + if (NonRefTy->getPointeeType()->isCharType()) + return CharPtrToString((char *)V.getPtr()); + + return VoidPtrToString(V.getPtr()); + } + + // Fall back to printing just the address of the unknown object. + return "@" + VoidPtrToString(V.getPtr()); +} + +std::string Interpreter::ValueTypeToString(const Value &V) const { + ASTContext &Ctx = const_cast(V.getASTContext()); + QualType QT = V.getType(); + + std::string QTStr = QualTypeToString(Ctx, QT); + + if (QT->isReferenceType()) + QTStr += " &"; + + return QTStr; +} + llvm::Expected -Interpreter::CompileDtorCall(CXXRecordDecl *CXXRD) { +Interpreter::CompileDtorCall(CXXRecordDecl *CXXRD) const { assert(CXXRD && "Cannot compile a destructor for a nullptr"); if (auto Dtor = Dtors.find(CXXRD); Dtor != Dtors.end()) return Dtor->getSecond(); @@ -81,7 +404,7 @@ class InterfaceKindVisitor return InterfaceKind::CopyArray; } - InterfaceKind VisitFunctionProtoType(const FunctionProtoType *Ty) { + InterfaceKind VisitFunctionType(const FunctionType *Ty) { HandlePtrType(Ty); return InterfaceKind::NoAlloc; } @@ -141,9 +464,14 @@ class InterfaceKindVisitor } }; +static constexpr llvm::StringRef VPName[] = { + "__clang_Interpreter_SetValueNoAlloc", + "__clang_Interpreter_SetValueWithAlloc", + "__clang_Interpreter_SetValueCopyArr", "__ci_newtag"}; + // This synthesizes a call expression to a speciall // function that is responsible for generating the Value. -// In general, we transform: +// In general, we transform c++: // clang-repl> x // To: // // 1. If x is a built-in type like int, float. @@ -154,7 +482,7 @@ class InterfaceKindVisitor // // 3. If x is a struct, but a rvalue. // new (__clang_Interpreter_SetValueWithAlloc(ThisInterp, OpaqueValue, // xQualType)) (x); -llvm::Expected Interpreter::ExtractValueFromExpr(Expr *E) { +llvm::Expected Interpreter::convertExprToValue(Expr *E) { Sema &S = getCompilerInstance()->getSema(); ASTContext &Ctx = S.getASTContext(); @@ -176,23 +504,21 @@ llvm::Expected Interpreter::ExtractValueFromExpr(Expr *E) { Interface = S.BuildDeclarationNameExpr(CSS, R, /*ADL=*/false).get(); return llvm::Error::success(); }; - static constexpr llvm::StringRef Builtin[] = { - "__clang_Interpreter_SetValueNoAlloc", - "__clang_Interpreter_SetValueWithAlloc", - "__clang_Interpreter_SetValueCopyArr", "__ci_newtag"}; if (llvm::Error Err = - LookupInterface(ValuePrintingInfo[NoAlloc], Builtin[NoAlloc])) + LookupInterface(ValuePrintingInfo[NoAlloc], VPName[NoAlloc])) + return std::move(Err); + + if (llvm::Error Err = + LookupInterface(ValuePrintingInfo[CopyArray], VPName[CopyArray])) + return std::move(Err); + + if (llvm::Error Err = + LookupInterface(ValuePrintingInfo[WithAlloc], VPName[WithAlloc])) return std::move(Err); if (Ctx.getLangOpts().CPlusPlus) { if (llvm::Error Err = - LookupInterface(ValuePrintingInfo[WithAlloc], Builtin[WithAlloc])) - return std::move(Err); - if (llvm::Error Err = - LookupInterface(ValuePrintingInfo[CopyArray], Builtin[CopyArray])) - return std::move(Err); - if (llvm::Error Err = - LookupInterface(ValuePrintingInfo[NewTag], Builtin[NewTag])) + LookupInterface(ValuePrintingInfo[NewTag], VPName[NewTag])) return std::move(Err); } } @@ -211,7 +537,7 @@ llvm::Expected Interpreter::ExtractValueFromExpr(Expr *E) { if (auto *EWC = llvm::dyn_cast_if_present(E)) E = EWC->getSubExpr(); - QualType Ty = E->getType(); + QualType Ty = E->IgnoreImpCasts()->getType(); QualType DesugaredTy = Ty.getDesugaredType(Ctx); // For lvalue struct, we treat it as a reference. @@ -239,7 +565,10 @@ llvm::Expected Interpreter::ExtractValueFromExpr(Expr *E) { ExprResult AllocCall = S.ActOnCallExpr(Scope, ValuePrintingInfo[InterfaceKind::WithAlloc], E->getBeginLoc(), AdjustedArgs, E->getEndLoc()); - assert(!AllocCall.isInvalid() && "Can't create runtime interface call!"); + if (AllocCall.isInvalid()) + return llvm::make_error( + "Cannot call to " + VPName[WithAlloc], + llvm::inconvertibleErrorCode()); TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation()); @@ -253,14 +582,23 @@ llvm::Expected Interpreter::ExtractValueFromExpr(Expr *E) { // __clang_Interpreter_SetValueCopyArr. if (Kind == InterfaceKind::CopyArray) { - const auto *ConstantArrTy = - cast(DesugaredTy.getTypePtr()); - size_t ArrSize = Ctx.getConstantArrayElementCount(ConstantArrTy); + const auto *CATy = cast(DesugaredTy.getTypePtr()); + size_t ArrSize = Ctx.getConstantArrayElementCount(CATy); + + if (!Ctx.getLangOpts().CPlusPlus) + ArrSize *= Ctx.getTypeSizeInChars(CATy->getBaseElementTypeUnsafe()) + .getQuantity(); + Expr *ArrSizeExpr = IntegerLiteralExpr(Ctx, ArrSize); Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr}; SetValueE = S.ActOnCallExpr(Scope, ValuePrintingInfo[InterfaceKind::CopyArray], SourceLocation(), Args, SourceLocation()); + if (SetValueE.isInvalid()) + return llvm::make_error( + "Cannot call to " + VPName[CopyArray], + llvm::inconvertibleErrorCode()); + break; } Expr *Args[] = {AllocCall.get(), ValuePrintingInfo[InterfaceKind::NewTag]}; ExprResult CXXNewCall = S.BuildCXXNew( @@ -270,8 +608,10 @@ llvm::Expected Interpreter::ExtractValueFromExpr(Expr *E) { /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt, E->getSourceRange(), E); - assert(!CXXNewCall.isInvalid() && - "Can't create runtime placement new call!"); + if (CXXNewCall.isInvalid()) + return llvm::make_error( + "Cannot build a call to placement new", + llvm::inconvertibleErrorCode()); SetValueE = S.ActOnFinishFullExpr(CXXNewCall.get(), /*DiscardedValue=*/false); @@ -300,6 +640,7 @@ llvm::Expected Interpreter::ExtractValueFromExpr(Expr *E) { using namespace clang; // Temporary rvalue struct that need special care. +extern "C" { REPL_EXTERNAL_VISIBILITY void * __clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal, void *OpaqueType) { @@ -308,8 +649,9 @@ __clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal, return VRef.getPtr(); } -extern "C" void REPL_EXTERNAL_VISIBILITY __clang_Interpreter_SetValueNoAlloc( - void *This, void *OutVal, void *OpaqueType, ...) { +REPL_EXTERNAL_VISIBILITY void +__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, + ...) { Value &VRef = *(Value *)OutVal; Interpreter *I = static_cast(This); VRef = Value(I, OpaqueType); @@ -384,6 +726,7 @@ extern "C" void REPL_EXTERNAL_VISIBILITY __clang_Interpreter_SetValueNoAlloc( } va_end(args); } +} // A trampoline to work around the fact that operator placement new cannot // really be forward declared due to libc++ and libstdc++ declaration mismatch. diff --git a/clang/lib/Interpreter/Value.cpp b/clang/lib/Interpreter/Value.cpp index afdf406b37253..be2ab5587a980 100644 --- a/clang/lib/Interpreter/Value.cpp +++ b/clang/lib/Interpreter/Value.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Interpreter/Value.h" +#include "InterpreterUtils.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Type.h" #include "clang/Interpreter/Interpreter.h" @@ -19,6 +20,8 @@ #include #include +using namespace clang; + namespace { // This is internal buffer maintained by Value, used to hold temporaries. @@ -117,8 +120,9 @@ static Value::Kind ConvertQualTypeToKind(const ASTContext &Ctx, QualType QT) { } } -Value::Value(Interpreter *In, void *Ty) : Interp(In), OpaqueType(Ty) { - setKind(ConvertQualTypeToKind(getASTContext(), getType())); +Value::Value(const Interpreter *In, void *Ty) : Interp(In), OpaqueType(Ty) { + const ASTContext &C = getASTContext(); + setKind(ConvertQualTypeToKind(C, getType())); if (ValueKind == K_PtrOrObj) { QualType Canon = getType().getCanonicalType(); if ((Canon->isPointerType() || Canon->isObjectType() || @@ -127,7 +131,7 @@ Value::Value(Interpreter *In, void *Ty) : Interp(In), OpaqueType(Ty) { Canon->isMemberPointerType())) { IsManuallyAlloc = true; // Compile dtor function. - Interpreter &Interp = getInterpreter(); + const Interpreter &Interp = getInterpreter(); void *DtorF = nullptr; size_t ElementsSize = 1; QualType DtorTy = getType(); @@ -228,14 +232,13 @@ void *Value::getPtr() const { return Data.m_Ptr; } -QualType Value::getType() const { - return QualType::getFromOpaquePtr(OpaqueType); +void Value::setRawBits(void *Ptr, unsigned NBits /*= sizeof(Storage)*/) { + assert(NBits <= sizeof(Storage) && "Greater than the total size"); + memcpy(/*dest=*/Data.m_RawBits, /*src=*/Ptr, /*nbytes=*/NBits / 8); } -Interpreter &Value::getInterpreter() { - assert(Interp != nullptr && - "Can't get interpreter from a default constructed value"); - return *Interp; +QualType Value::getType() const { + return QualType::getFromOpaquePtr(OpaqueType); } const Interpreter &Value::getInterpreter() const { @@ -244,8 +247,6 @@ const Interpreter &Value::getInterpreter() const { return *Interp; } -ASTContext &Value::getASTContext() { return getInterpreter().getASTContext(); } - const ASTContext &Value::getASTContext() const { return getInterpreter().getASTContext(); } @@ -253,14 +254,32 @@ const ASTContext &Value::getASTContext() const { void Value::dump() const { print(llvm::outs()); } void Value::printType(llvm::raw_ostream &Out) const { - Out << "Not implement yet.\n"; + Out << Interp->ValueTypeToString(*this); } + void Value::printData(llvm::raw_ostream &Out) const { - Out << "Not implement yet.\n"; + Out << Interp->ValueDataToString(*this); } +// FIXME: We do not support the multiple inheritance case where one of the base +// classes has a pretty-printer and the other does not. void Value::print(llvm::raw_ostream &Out) const { assert(OpaqueType != nullptr && "Can't print default Value"); - Out << "Not implement yet.\n"; + + // Don't even try to print a void or an invalid type, it doesn't make sense. + if (getType()->isVoidType() || !isValid()) + return; + + // We need to get all the results together then print it, since `printType` is + // much faster than `printData`. + std::string Str; + llvm::raw_string_ostream SS(Str); + + SS << "("; + printType(SS); + SS << ") "; + printData(SS); + SS << "\n"; + Out << Str; } } // namespace clang diff --git a/clang/lib/Lex/DependencyDirectivesScanner.cpp b/clang/lib/Lex/DependencyDirectivesScanner.cpp index 869c9cea566b6..9ccff5e3342d5 100644 --- a/clang/lib/Lex/DependencyDirectivesScanner.cpp +++ b/clang/lib/Lex/DependencyDirectivesScanner.cpp @@ -560,15 +560,13 @@ bool Scanner::lexModuleDirectiveBody(DirectiveKind Kind, const char *&First, if (Tok.is(tok::semi)) break; } + + const auto &Tok = lexToken(First, End); pushDirective(Kind); - skipWhitespace(First, End); - if (First == End) + if (Tok.is(tok::eof) || Tok.is(tok::eod)) return false; - if (!isVerticalWhitespace(*First)) - return reportError( - DirectiveLoc, diag::err_dep_source_scanner_unexpected_tokens_at_import); - skipNewline(First, End); - return false; + return reportError(DirectiveLoc, + diag::err_dep_source_scanner_unexpected_tokens_at_import); } dependency_directives_scan::Token &Scanner::lexToken(const char *&First, @@ -735,6 +733,13 @@ bool Scanner::lexModule(const char *&First, const char *const End) { return false; break; } + case ';': { + // Handle the global module fragment `module;`. + if (Id == "module" && !Export) + break; + skipLine(First, End); + return false; + } case '<': case '"': break; @@ -905,14 +910,6 @@ bool Scanner::lexPPLine(const char *&First, const char *const End) { CurDirToks.clear(); }); - // Handle "@import". - if (*First == '@') - return lexAt(First, End); - - // Handle module directives for C++20 modules. - if (*First == 'i' || *First == 'e' || *First == 'm') - return lexModule(First, End); - if (*First == '_') { if (isNextIdentifierOrSkipLine("_Pragma", First, End)) return lex_Pragma(First, End); @@ -925,6 +922,14 @@ bool Scanner::lexPPLine(const char *&First, const char *const End) { auto ScEx2 = make_scope_exit( [&]() { TheLexer.setParsingPreprocessorDirective(false); }); + // Handle "@import". + if (*First == '@') + return lexAt(First, End); + + // Handle module directives for C++20 modules. + if (*First == 'i' || *First == 'e' || *First == 'm') + return lexModule(First, End); + // Lex '#'. const dependency_directives_scan::Token &HashTok = lexToken(First, End); if (HashTok.is(tok::hashhash)) { diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp index a62508e3e27bf..5b08d7f0efe5a 100644 --- a/clang/lib/Lex/LiteralSupport.cpp +++ b/clang/lib/Lex/LiteralSupport.cpp @@ -1467,7 +1467,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { if (s != PossibleNewDigitStart) DigitsBegin = PossibleNewDigitStart; else - IsSingleZero = (s == ThisTokEnd); // Is the only thing we've seen a 0? + IsSingleZero = (s == ThisTokBegin + 1); if (s == ThisTokEnd) return; // Done, simple octal number like 01234 diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp index 01c85e6ad95d5..bba3c89bed38f 100644 --- a/clang/lib/Lex/Pragma.cpp +++ b/clang/lib/Lex/Pragma.cpp @@ -591,7 +591,8 @@ IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) { } // Remember the macro string. - std::string StrVal = getSpelling(Tok); + Token StrTok = Tok; + std::string StrVal = getSpelling(StrTok); // Read the ')'. Lex(Tok); @@ -604,6 +605,15 @@ IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) { assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' && "Invalid string token!"); + if (StrVal.size() <= 2) { + Diag(StrTok.getLocation(), diag::warn_pargma_push_pop_macro_empty_string) + << SourceRange( + StrTok.getLocation(), + StrTok.getLocation().getLocWithOffset(StrTok.getLength())) + << PragmaTok.getIdentifierInfo()->isStr("pop_macro"); + return nullptr; + } + // Create a Token from the string. Token MacroTok; MacroTok.startToken(); diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index bcd3ea60ce3da..e278846f6f36d 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -950,6 +950,8 @@ void Preprocessor::Lex(Token &Result) { case tok::period: ModuleDeclState.handlePeriod(); break; + case tok::eod: + break; case tok::identifier: // Check "import" and "module" when there is no open bracket. The two // identifiers are not meaningful with open brackets. diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 9cae4f9a23ef0..31392d1dd8d4b 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -591,8 +591,7 @@ bool Parser::ParseUsingDeclarator(DeclaratorContext Context, NextToken().isRegularKeywordAttribute() || NextToken().is(tok::kw___attribute)) && D.SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() && - !D.SS.getScopeRep()->getAsNamespace() && - !D.SS.getScopeRep()->getAsNamespaceAlias()) { + D.SS.getScopeRep()->getKind() != NestedNameSpecifier::Namespace) { SourceLocation IdLoc = ConsumeToken(); ParsedType Type = Actions.getInheritingConstructorName(D.SS, IdLoc, *LastII); diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 31b84b6f2ede0..bf1978c22ee9f 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -541,7 +541,8 @@ StmtResult Parser::ParseExprStatement(ParsedStmtContext StmtCtx) { } Token *CurTok = nullptr; - // Note we shouldn't eat the token since the callback needs it. + // If the semicolon is missing at the end of REPL input, we want to print + // the result. Note we shouldn't eat the token since the callback needs it. if (Tok.is(tok::annot_repl_input_end)) CurTok = &Tok; else diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 8834bf80c4016..ff50b3f83908c 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -2519,6 +2519,7 @@ Decl *Parser::ParseModuleImport(SourceLocation AtLoc, break; } ExpectAndConsumeSemi(diag::err_module_expected_semi); + TryConsumeToken(tok::eod); if (SeenError) return nullptr; diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 5eba024e83634..829c81bab16f5 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -522,8 +522,7 @@ static bool areAllValuesNoReturn(const VarDecl *VD, const CFGBlock &VarBlk, } // If all checked blocks satisfy the condition, the check is finished. - if (std::all_of(BlocksToCheck.begin(), BlocksToCheck.end(), - BlockSatisfiesCondition)) + if (llvm::all_of(BlocksToCheck, BlockSatisfiesCondition)) return true; // If this block does not contain the variable definition, check @@ -2902,8 +2901,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings( .setAlwaysAdd(Stmt::UnaryOperatorClass); } - bool EnableLifetimeSafetyAnalysis = !Diags.isIgnored( - diag::warn_experimental_lifetime_safety_dummy_warning, D->getBeginLoc()); + bool EnableLifetimeSafetyAnalysis = S.getLangOpts().EnableLifetimeSafety; // Install the logical handler. std::optional LEH; if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) { @@ -3030,8 +3028,8 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings( // TODO: Enable lifetime safety analysis for other languages once it is // stable. if (EnableLifetimeSafetyAnalysis && S.getLangOpts().CPlusPlus) { - if (CFG *cfg = AC.getCFG()) - runLifetimeSafetyAnalysis(*cast(D), *cfg, AC); + if (AC.getCFG()) + lifetimes::runLifetimeSafetyAnalysis(AC); } // Check for violations of "called once" parameter properties. if (S.getLangOpts().ObjC && !S.getLangOpts().CPlusPlus && diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index ee5a862c32509..f0f1d66f66e93 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -72,7 +72,7 @@ void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier, "NestedNameSpecifierLoc range computation incorrect"); } -void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace, +void CXXScopeSpec::Extend(ASTContext &Context, NamespaceBaseDecl *Namespace, SourceLocation NamespaceLoc, SourceLocation ColonColonLoc) { Builder.Extend(Context, Namespace, NamespaceLoc, ColonColonLoc); @@ -85,19 +85,6 @@ void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace, "NestedNameSpecifierLoc range computation incorrect"); } -void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias, - SourceLocation AliasLoc, - SourceLocation ColonColonLoc) { - Builder.Extend(Context, Alias, AliasLoc, ColonColonLoc); - - if (Range.getBegin().isInvalid()) - Range.setBegin(AliasLoc); - Range.setEnd(ColonColonLoc); - - assert(Range == Builder.getSourceRange() && - "NestedNameSpecifierLoc range computation incorrect"); -} - void CXXScopeSpec::MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc) { Builder.MakeGlobal(Context, ColonColonLoc); diff --git a/clang/lib/Sema/SemaAMDGPU.cpp b/clang/lib/Sema/SemaAMDGPU.cpp index e6414a623b929..c23c98aa3aaeb 100644 --- a/clang/lib/Sema/SemaAMDGPU.cpp +++ b/clang/lib/Sema/SemaAMDGPU.cpp @@ -36,6 +36,7 @@ bool SemaAMDGPU::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID, switch (BuiltinID) { case AMDGPU::BI__builtin_amdgcn_raw_ptr_buffer_load_lds: + case AMDGPU::BI__builtin_amdgcn_struct_ptr_buffer_load_lds: case AMDGPU::BI__builtin_amdgcn_load_to_lds: case AMDGPU::BI__builtin_amdgcn_global_load_lds: { constexpr const int SizeIdx = 2; diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp index bd603a925d15e..8e27fabccd583 100644 --- a/clang/lib/Sema/SemaARM.cpp +++ b/clang/lib/Sema/SemaARM.cpp @@ -1535,4 +1535,95 @@ bool SemaARM::areLaxCompatibleSveTypes(QualType FirstType, IsLaxCompatible(SecondType, FirstType); } +bool SemaARM::checkTargetVersionAttr(const StringRef Param, + const SourceLocation Loc) { + using namespace DiagAttrParams; + + llvm::SmallVector Features; + Param.split(Features, '+'); + for (StringRef Feat : Features) { + Feat = Feat.trim(); + if (Feat == "default") + continue; + if (!getASTContext().getTargetInfo().validateCpuSupports(Feat)) + return Diag(Loc, diag::warn_unsupported_target_attribute) + << Unsupported << None << Feat << TargetVersion; + } + return false; +} + +bool SemaARM::checkTargetClonesAttr( + SmallVectorImpl &Params, SmallVectorImpl &Locs, + SmallVectorImpl> &NewParams) { + using namespace DiagAttrParams; + + if (!getASTContext().getTargetInfo().hasFeature("fmv")) + return true; + + assert(Params.size() == Locs.size() && + "Mismatch between number of string parameters and locations"); + + bool HasDefault = false; + bool HasNonDefault = false; + for (unsigned I = 0, E = Params.size(); I < E; ++I) { + const StringRef Param = Params[I].trim(); + const SourceLocation &Loc = Locs[I]; + + if (Param.empty()) + return Diag(Loc, diag::warn_unsupported_target_attribute) + << Unsupported << None << "" << TargetClones; + + if (Param == "default") { + if (HasDefault) + Diag(Loc, diag::warn_target_clone_duplicate_options); + else { + NewParams.push_back(Param); + HasDefault = true; + } + continue; + } + + bool HasCodeGenImpact = false; + llvm::SmallVector Features; + llvm::SmallVector ValidFeatures; + Param.split(Features, '+'); + for (StringRef Feat : Features) { + Feat = Feat.trim(); + if (!getASTContext().getTargetInfo().validateCpuSupports(Feat)) { + Diag(Loc, diag::warn_unsupported_target_attribute) + << Unsupported << None << Feat << TargetClones; + continue; + } + if (getASTContext().getTargetInfo().doesFeatureAffectCodeGen(Feat)) + HasCodeGenImpact = true; + ValidFeatures.push_back(Feat); + } + + // Ignore features that don't impact code generation. + if (!HasCodeGenImpact) { + Diag(Loc, diag::warn_target_clone_no_impact_options); + continue; + } + + if (ValidFeatures.empty()) + continue; + + // Canonicalize attribute parameter. + llvm::sort(ValidFeatures); + SmallString<64> NewParam(llvm::join(ValidFeatures, "+")); + if (llvm::is_contained(NewParams, NewParam)) { + Diag(Loc, diag::warn_target_clone_duplicate_options); + continue; + } + + // Valid non-default argument. + NewParams.push_back(NewParam); + HasNonDefault = true; + } + if (!HasNonDefault) + return true; + + return false; +} + } // namespace clang diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index ab83f625d2849..6ac04837708f6 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -137,10 +137,7 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, llvm_unreachable("Dependent nested-name-specifier has no DeclContext"); case NestedNameSpecifier::Namespace: - return NNS->getAsNamespace(); - - case NestedNameSpecifier::NamespaceAlias: - return NNS->getAsNamespaceAlias()->getNamespace(); + return NNS->getAsNamespace()->getNamespace(); case NestedNameSpecifier::TypeSpec: { const TagType *Tag = NNS->getAsType()->getAs(); @@ -992,7 +989,6 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { switch (Qualifier->getKind()) { case NestedNameSpecifier::Global: case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: // These are always namespace scopes. We never want to enter a // namespace scope from anything but a file context. return CurContext->getRedeclContext()->isFileContext(); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index dd5b710d7e1d4..c74b67106ad74 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3013,6 +3013,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, case Builtin::BI__builtin_elementwise_maxnum: case Builtin::BI__builtin_elementwise_minimum: case Builtin::BI__builtin_elementwise_maximum: + case Builtin::BI__builtin_elementwise_minimumnum: + case Builtin::BI__builtin_elementwise_maximumnum: case Builtin::BI__builtin_elementwise_atan2: case Builtin::BI__builtin_elementwise_fmod: case Builtin::BI__builtin_elementwise_pow: @@ -5239,7 +5241,9 @@ bool Sema::BuiltinVAStartARMMicrosoft(CallExpr *Call) { << 2 << Arg1->getType() << ConstCharPtrTy; const QualType SizeTy = Context.getSizeType(); - if (Arg2Ty->getCanonicalTypeInternal().withoutLocalFastQualifiers() != SizeTy) + if (!Context.hasSameType( + Arg2Ty->getCanonicalTypeInternal().withoutLocalFastQualifiers(), + SizeTy)) Diag(Arg2->getBeginLoc(), diag::err_typecheck_convert_incompatible) << Arg2->getType() << SizeTy << 1 /* different class */ << 0 /* qualifier difference */ diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 834417f8e15ac..5205ca0bca6fa 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -925,7 +925,12 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction( ND && ND->isFunctionOrFunctionTemplate()) { ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true); const FunctionDecl *FD = ND->getAsFunction(); + if (FunctionTemplateDecl *Template = FD->getDescribedFunctionTemplate(); + Template && Template->getInstantiatedFromMemberTemplate()) + FD = Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl(); for (auto *PVD : FD->parameters()) { + if (ScopeForParameters->getInstantiationOfIfExists(PVD)) + continue; if (!PVD->isParameterPack()) { ScopeForParameters->InstantiatedLocal(PVD, PVD); continue; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 78f4804202ddc..9a2950cf1648e 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3254,9 +3254,8 @@ static void handleCodeSegAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) { - enum FirstParam { Unsupported, Duplicate, Unknown }; - enum SecondParam { None, CPU, Tune }; - enum ThirdParam { Target, TargetClones }; + using namespace DiagAttrParams; + if (AttrStr.contains("fpmath=")) return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) << Unsupported << None << "fpmath=" << Target; @@ -3331,80 +3330,22 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) { return false; } -bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D, - StringRef AttrStr) { - enum FirstParam { Unsupported }; - enum SecondParam { None }; - enum ThirdParam { Target, TargetClones, TargetVersion }; - llvm::SmallVector Features; - if (Context.getTargetInfo().getTriple().isRISCV()) { - llvm::SmallVector AttrStrs; - AttrStr.split(AttrStrs, ';'); - - bool HasArch = false; - bool HasPriority = false; - bool HasDefault = false; - bool DuplicateAttr = false; - for (auto &AttrStr : AttrStrs) { - // Only support arch=+ext,... syntax. - if (AttrStr.starts_with("arch=+")) { - if (HasArch) - DuplicateAttr = true; - HasArch = true; - ParsedTargetAttr TargetAttr = - Context.getTargetInfo().parseTargetAttr(AttrStr); - - if (TargetAttr.Features.empty() || - llvm::any_of(TargetAttr.Features, [&](const StringRef Ext) { - return !RISCV().isValidFMVExtension(Ext); - })) - return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) - << Unsupported << None << AttrStr << TargetVersion; - } else if (AttrStr.starts_with("default")) { - if (HasDefault) - DuplicateAttr = true; - HasDefault = true; - } else if (AttrStr.consume_front("priority=")) { - if (HasPriority) - DuplicateAttr = true; - HasPriority = true; - unsigned Digit; - if (AttrStr.getAsInteger(0, Digit)) - return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) - << Unsupported << None << AttrStr << TargetVersion; - } else { - return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) - << Unsupported << None << AttrStr << TargetVersion; - } - } - - if (((HasPriority || HasArch) && HasDefault) || DuplicateAttr || - (HasPriority && !HasArch)) - return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) - << Unsupported << None << AttrStr << TargetVersion; +static void handleTargetVersionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + StringRef Param; + SourceLocation Loc; + if (!S.checkStringLiteralArgumentAttr(AL, 0, Param, &Loc)) + return; - return false; - } - AttrStr.split(Features, "+"); - for (auto &CurFeature : Features) { - CurFeature = CurFeature.trim(); - if (CurFeature == "default") - continue; - if (!Context.getTargetInfo().validateCpuSupports(CurFeature)) - return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) - << Unsupported << None << CurFeature << TargetVersion; + if (S.Context.getTargetInfo().getTriple().isAArch64()) { + if (S.ARM().checkTargetVersionAttr(Param, Loc)) + return; + } else if (S.Context.getTargetInfo().getTriple().isRISCV()) { + if (S.RISCV().checkTargetVersionAttr(Param, Loc)) + return; } - return false; -} -static void handleTargetVersionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - StringRef Str; - SourceLocation LiteralLoc; - if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc) || - S.checkTargetVersionAttr(LiteralLoc, D, Str)) - return; TargetVersionAttr *NewAttr = - ::new (S.Context) TargetVersionAttr(S.Context, AL, Str); + ::new (S.Context) TargetVersionAttr(S.Context, AL, Param); D->addAttr(NewAttr); } @@ -3419,158 +3360,7 @@ static void handleTargetAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(NewAttr); } -bool Sema::checkTargetClonesAttrString( - SourceLocation LiteralLoc, StringRef Str, const StringLiteral *Literal, - Decl *D, bool &HasDefault, bool &HasCommas, bool &HasNotDefault, - SmallVectorImpl> &StringsBuffer) { - enum FirstParam { Unsupported, Duplicate, Unknown }; - enum SecondParam { None, CPU, Tune }; - enum ThirdParam { Target, TargetClones }; - HasCommas = HasCommas || Str.contains(','); - const TargetInfo &TInfo = Context.getTargetInfo(); - // Warn on empty at the beginning of a string. - if (Str.size() == 0) - return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) - << Unsupported << None << "" << TargetClones; - - std::pair Parts = {{}, Str}; - while (!Parts.second.empty()) { - Parts = Parts.second.split(','); - StringRef Cur = Parts.first.trim(); - SourceLocation CurLoc = - Literal->getLocationOfByte(Cur.data() - Literal->getString().data(), - getSourceManager(), getLangOpts(), TInfo); - - bool DefaultIsDupe = false; - bool HasCodeGenImpact = false; - if (Cur.empty()) - return Diag(CurLoc, diag::warn_unsupported_target_attribute) - << Unsupported << None << "" << TargetClones; - - if (TInfo.getTriple().isAArch64()) { - // AArch64 target clones specific - if (Cur == "default") { - DefaultIsDupe = HasDefault; - HasDefault = true; - if (llvm::is_contained(StringsBuffer, Cur) || DefaultIsDupe) - Diag(CurLoc, diag::warn_target_clone_duplicate_options); - else - StringsBuffer.push_back(Cur); - } else { - std::pair CurParts = {{}, Cur}; - llvm::SmallVector CurFeatures; - while (!CurParts.second.empty()) { - CurParts = CurParts.second.split('+'); - StringRef CurFeature = CurParts.first.trim(); - if (!TInfo.validateCpuSupports(CurFeature)) { - Diag(CurLoc, diag::warn_unsupported_target_attribute) - << Unsupported << None << CurFeature << TargetClones; - continue; - } - if (TInfo.doesFeatureAffectCodeGen(CurFeature)) - HasCodeGenImpact = true; - CurFeatures.push_back(CurFeature); - } - // Canonize TargetClones Attributes - llvm::sort(CurFeatures); - SmallString<64> Res; - for (auto &CurFeat : CurFeatures) { - if (!Res.empty()) - Res.append("+"); - Res.append(CurFeat); - } - if (llvm::is_contained(StringsBuffer, Res) || DefaultIsDupe) - Diag(CurLoc, diag::warn_target_clone_duplicate_options); - else if (!HasCodeGenImpact) - // Ignore features in target_clone attribute that don't impact - // code generation - Diag(CurLoc, diag::warn_target_clone_no_impact_options); - else if (!Res.empty()) { - StringsBuffer.push_back(Res); - HasNotDefault = true; - } - } - } else if (TInfo.getTriple().isRISCV()) { - // Suppress warn_target_clone_mixed_values - HasCommas = false; - - // Cur is split's parts of Str. RISC-V uses Str directly, - // so skip when encountered more than once. - if (!Str.starts_with(Cur)) - continue; - - llvm::SmallVector AttrStrs; - Str.split(AttrStrs, ";"); - - bool IsPriority = false; - bool IsDefault = false; - for (auto &AttrStr : AttrStrs) { - // Only support arch=+ext,... syntax. - if (AttrStr.starts_with("arch=+")) { - ParsedTargetAttr TargetAttr = - Context.getTargetInfo().parseTargetAttr(AttrStr); - - if (TargetAttr.Features.empty() || - llvm::any_of(TargetAttr.Features, [&](const StringRef Ext) { - return !RISCV().isValidFMVExtension(Ext); - })) - return Diag(CurLoc, diag::warn_unsupported_target_attribute) - << Unsupported << None << Str << TargetClones; - } else if (AttrStr.starts_with("default")) { - IsDefault = true; - DefaultIsDupe = HasDefault; - HasDefault = true; - } else if (AttrStr.consume_front("priority=")) { - IsPriority = true; - unsigned Digit; - if (AttrStr.getAsInteger(0, Digit)) - return Diag(CurLoc, diag::warn_unsupported_target_attribute) - << Unsupported << None << Str << TargetClones; - } else { - return Diag(CurLoc, diag::warn_unsupported_target_attribute) - << Unsupported << None << Str << TargetClones; - } - } - - if (IsPriority && IsDefault) - return Diag(CurLoc, diag::warn_unsupported_target_attribute) - << Unsupported << None << Str << TargetClones; - - if (llvm::is_contained(StringsBuffer, Str) || DefaultIsDupe) - Diag(CurLoc, diag::warn_target_clone_duplicate_options); - StringsBuffer.push_back(Str); - } else { - // Other targets ( currently X86 ) - if (Cur.starts_with("arch=")) { - if (!Context.getTargetInfo().isValidCPUName( - Cur.drop_front(sizeof("arch=") - 1))) - return Diag(CurLoc, diag::warn_unsupported_target_attribute) - << Unsupported << CPU << Cur.drop_front(sizeof("arch=") - 1) - << TargetClones; - } else if (Cur == "default") { - DefaultIsDupe = HasDefault; - HasDefault = true; - } else if (!Context.getTargetInfo().isValidFeatureName(Cur) || - Context.getTargetInfo().getFMVPriority(Cur) == 0) - return Diag(CurLoc, diag::warn_unsupported_target_attribute) - << Unsupported << None << Cur << TargetClones; - if (llvm::is_contained(StringsBuffer, Cur) || DefaultIsDupe) - Diag(CurLoc, diag::warn_target_clone_duplicate_options); - // Note: Add even if there are duplicates, since it changes name mangling. - StringsBuffer.push_back(Cur); - } - } - if (Str.rtrim().ends_with(",")) - return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) - << Unsupported << None << "" << TargetClones; - return false; -} - static void handleTargetClonesAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (S.Context.getTargetInfo().getTriple().isAArch64() && - !S.Context.getTargetInfo().hasFeature("fmv")) - return; - // Ensure we don't combine these with themselves, since that causes some // confusing behavior. if (const auto *Other = D->getAttr()) { @@ -3581,31 +3371,6 @@ static void handleTargetClonesAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (checkAttrMutualExclusion(S, D, AL)) return; - SmallVector Strings; - SmallVector, 2> StringsBuffer; - bool HasCommas = false, HasDefault = false, HasNotDefault = false; - - for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) { - StringRef CurStr; - SourceLocation LiteralLoc; - if (!S.checkStringLiteralArgumentAttr(AL, I, CurStr, &LiteralLoc) || - S.checkTargetClonesAttrString( - LiteralLoc, CurStr, - cast(AL.getArgAsExpr(I)->IgnoreParenCasts()), D, - HasDefault, HasCommas, HasNotDefault, StringsBuffer)) - return; - } - for (auto &SmallStr : StringsBuffer) - Strings.push_back(SmallStr.str()); - - if (HasCommas && AL.getNumArgs() > 1) - S.Diag(AL.getLoc(), diag::warn_target_clone_mixed_values); - - if (!HasDefault && !S.Context.getTargetInfo().getTriple().isAArch64()) { - S.Diag(AL.getLoc(), diag::err_target_clone_must_have_default); - return; - } - // FIXME: We could probably figure out how to get this to work for lambdas // someday. if (const auto *MD = dyn_cast(D)) { @@ -3617,13 +3382,34 @@ static void handleTargetClonesAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } } - // No multiversion if we have default version only. - if (S.Context.getTargetInfo().getTriple().isAArch64() && !HasNotDefault) - return; + SmallVector Params; + SmallVector Locations; + for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) { + StringRef Param; + SourceLocation Loc; + if (!S.checkStringLiteralArgumentAttr(AL, I, Param, &Loc)) + return; + Params.push_back(Param); + Locations.push_back(Loc); + } + + SmallVector, 2> NewParams; + if (S.Context.getTargetInfo().getTriple().isAArch64()) { + if (S.ARM().checkTargetClonesAttr(Params, Locations, NewParams)) + return; + } else if (S.Context.getTargetInfo().getTriple().isRISCV()) { + if (S.RISCV().checkTargetClonesAttr(Params, Locations, NewParams)) + return; + } else if (S.Context.getTargetInfo().getTriple().isX86()) { + if (S.X86().checkTargetClonesAttr(Params, Locations, NewParams)) + return; + } + Params.clear(); + for (auto &SmallStr : NewParams) + Params.push_back(SmallStr.str()); - cast(D)->setIsMultiVersion(); TargetClonesAttr *NewAttr = ::new (S.Context) - TargetClonesAttr(S.Context, AL, Strings.data(), Strings.size()); + TargetClonesAttr(S.Context, AL, Params.data(), Params.size()); D->addAttr(NewAttr); } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index f60ab4f0da7a0..f5b4614576086 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -11930,7 +11930,7 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, /// getNamespaceDecl - Returns the namespace a decl represents. If the decl /// is a namespace alias, returns the namespace it points to. -static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) { +static inline NamespaceDecl *getNamespaceDecl(NamespaceBaseDecl *D) { if (NamespaceAliasDecl *AD = dyn_cast_or_null(D)) return AD->getNamespace(); return dyn_cast_or_null(D); @@ -13829,7 +13829,7 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc, } } assert(!R.isAmbiguous() && !R.empty()); - NamedDecl *ND = R.getRepresentativeDecl(); + auto *ND = cast(R.getRepresentativeDecl()); // Check if we have a previous declaration with the same name. LookupResult PrevR(*this, Alias, AliasLoc, LookupOrdinaryName, @@ -18682,7 +18682,7 @@ bool Sema::CheckOverridingFunctionAttributes(CXXMethodDecl *New, case FunctionEffectDiff::OverrideResult::NoAction: break; case FunctionEffectDiff::OverrideResult::Warn: - Diag(New->getLocation(), diag::warn_mismatched_func_effect_override) + Diag(New->getLocation(), diag::warn_conflicting_func_effect_override) << Diff.effectName(); Diag(Old->getLocation(), diag::note_overridden_virtual_function) << Old->getReturnTypeSourceRange(); @@ -18695,6 +18695,14 @@ bool Sema::CheckOverridingFunctionAttributes(CXXMethodDecl *New, QualType ModQT = Context.getFunctionType(NewFT->getReturnType(), NewFT->getParamTypes(), EPI); New->setType(ModQT); + if (Errs.empty()) { + // A warning here is somewhat pedantic. Skip this if there was + // already a merge conflict, which is more serious. + Diag(New->getLocation(), diag::warn_mismatched_func_effect_override) + << Diff.effectName(); + Diag(Old->getLocation(), diag::note_overridden_virtual_function) + << Old->getReturnTypeSourceRange(); + } break; } } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 728ada33e2e63..45c7178c6965d 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4564,6 +4564,9 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T, case Type::Atomic: T = cast(Ty)->getValueType(); break; + case Type::PredefinedSugar: + T = cast(Ty)->desugar(); + break; } } while (!T.isNull() && T->isVariablyModifiedType()); } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index f851c9e1d5015..0edfd6015cbd9 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -518,7 +518,6 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS, case NestedNameSpecifier::Global: case NestedNameSpecifier::Super: case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: return false; } @@ -3462,11 +3461,11 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, // non-templated allocation function we are trying to declare here. if (FunctionDecl *Func = dyn_cast(*Alloc)) { if (Func->getNumParams() == Params.size()) { - llvm::SmallVector FuncParams; - for (auto *P : Func->parameters()) - FuncParams.push_back( - Context.getCanonicalType(P->getType().getUnqualifiedType())); - if (llvm::ArrayRef(FuncParams) == Params) { + if (std::equal(Func->param_begin(), Func->param_end(), Params.begin(), + Params.end(), [&](ParmVarDecl *D, QualType RT) { + return Context.hasSameUnqualifiedType(D->getType(), + RT); + })) { // Make the function visible to name lookup, even if we found it in // an unimported module. It either is an implicitly-declared global // allocation function, or is suppressing that function. diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 95746b35f71ef..1c6f292454ed6 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3572,7 +3572,7 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, Designators.push_back(ASTDesignator::CreateFieldDesignator( D.getFieldDecl(), D.getDotLoc(), D.getFieldLoc())); } else if (D.isArrayDesignator()) { - Expr *Index = static_cast(D.getArrayIndex()); + Expr *Index = D.getArrayIndex(); llvm::APSInt IndexValue; if (!Index->isTypeDependent() && !Index->isValueDependent()) Index = CheckArrayDesignatorExpr(*this, Index, IndexValue).get(); @@ -3584,8 +3584,8 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, InitExpressions.push_back(Index); } } else if (D.isArrayRangeDesignator()) { - Expr *StartIndex = static_cast(D.getArrayRangeStart()); - Expr *EndIndex = static_cast(D.getArrayRangeEnd()); + Expr *StartIndex = D.getArrayRangeStart(); + Expr *EndIndex = D.getArrayRangeEnd(); llvm::APSInt StartValue; llvm::APSInt EndValue; bool StartDependent = StartIndex->isTypeDependent() || diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 6d6e07a2c03c7..8bde18f64f80b 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -4560,15 +4560,14 @@ static void getNestedNameSpecifierIdentifiers( II = NNS->getAsIdentifier(); break; - case NestedNameSpecifier::Namespace: - if (NNS->getAsNamespace()->isAnonymousNamespace()) + case NestedNameSpecifier::Namespace: { + const NamespaceBaseDecl *Namespace = NNS->getAsNamespace(); + if (const auto *NS = dyn_cast(Namespace); + NS && NS->isAnonymousNamespace()) return; - II = NNS->getAsNamespace()->getIdentifier(); - break; - - case NestedNameSpecifier::NamespaceAlias: - II = NNS->getAsNamespaceAlias()->getIdentifier(); + II = Namespace->getIdentifier(); break; + } case NestedNameSpecifier::TypeSpec: II = QualType(NNS->getAsType(), 0).getBaseTypeIdentifier(); diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index 46aa7dd0dcc21..128a5db57bf73 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -624,6 +624,66 @@ void SemaOpenACC::CheckDeclReference(SourceLocation Loc, Expr *E, Decl *D) { // loop (or we aren't in a loop!) so skip the diagnostic. } +namespace { +// Check whether the type of the thing we are referencing is OK for things like +// private, firstprivate, and reduction, which require certain operators to be +// available. +ExprResult CheckVarType(SemaOpenACC &S, OpenACCClauseKind CK, Expr *VarExpr, + Expr *InnerExpr) { + // There is nothing to do here, only these three have these sorts of + // restrictions. + if (CK != OpenACCClauseKind::Private && + CK != OpenACCClauseKind::FirstPrivate && + CK != OpenACCClauseKind::Reduction) + return VarExpr; + + // We can't test this if it isn't here, or if the type isn't clear yet. + if (!InnerExpr || InnerExpr->isTypeDependent()) + return VarExpr; + + const auto *RD = InnerExpr->getType()->getAsCXXRecordDecl(); + + // if this isn't a C++ record decl, we can create/copy/destroy this thing at + // will without problem, so this is a success. + if (!RD) + return VarExpr; + + // TODO: OpenACC: + // Private must have default ctor + dtor in InnerExpr + // FirstPrivate must have copyctor + dtor in InnerExpr + // Reduction must have copyctor + dtor + operation in InnerExpr + + // TODO OpenACC: It isn't clear what the requirements are for default + // constructor/copy constructor are for First private and reduction, but + // private requires a default constructor. + if (CK == OpenACCClauseKind::Private) { + bool HasNonDeletedDefaultCtor = + llvm::find_if(RD->ctors(), [](const CXXConstructorDecl *CD) { + return CD->isDefaultConstructor() && !CD->isDeleted(); + }) != RD->ctors().end(); + if (!HasNonDeletedDefaultCtor && !RD->needsImplicitDefaultConstructor()) { + S.Diag(InnerExpr->getBeginLoc(), + clang::diag::warn_acc_var_referenced_lacks_op) + << InnerExpr->getType() << CK + << clang::diag::AccVarReferencedReason::DefCtor; + return ExprError(); + } + } + + // All 3 things need to make sure they have a dtor. + bool DestructorDeleted = + RD->getDestructor() && RD->getDestructor()->isDeleted(); + if (DestructorDeleted && !RD->needsImplicitDestructor()) { + S.Diag(InnerExpr->getBeginLoc(), + clang::diag::warn_acc_var_referenced_lacks_op) + << InnerExpr->getType() << CK + << clang::diag::AccVarReferencedReason::Dtor; + return ExprError(); + } + return VarExpr; +} +} // namespace + ExprResult SemaOpenACC::ActOnVar(OpenACCDirectiveKind DK, OpenACCClauseKind CK, Expr *VarExpr) { // This has unique enough restrictions that we should split it to a separate @@ -660,7 +720,7 @@ ExprResult SemaOpenACC::ActOnVar(OpenACCDirectiveKind DK, OpenACCClauseKind CK, if (const auto *DRE = dyn_cast(CurVarExpr)) { if (isa( DRE->getFoundDecl()->getCanonicalDecl())) - return VarExpr; + return CheckVarType(*this, CK, VarExpr, CurVarExpr); } // If CK is a Reduction, this special cases for OpenACC3.3 2.5.15: "A var in a @@ -679,9 +739,9 @@ ExprResult SemaOpenACC::ActOnVar(OpenACCDirectiveKind DK, OpenACCClauseKind CK, // declare, reduction, and use_device. const auto *This = dyn_cast(ME->getBase()); if (This && This->isImplicit()) - return VarExpr; + return CheckVarType(*this, CK, VarExpr, CurVarExpr); } else { - return VarExpr; + return CheckVarType(*this, CK, VarExpr, CurVarExpr); } } } @@ -690,14 +750,14 @@ ExprResult SemaOpenACC::ActOnVar(OpenACCDirectiveKind DK, OpenACCClauseKind CK, // doesn't fall into 'variable or array name' if (CK != OpenACCClauseKind::UseDevice && DK != OpenACCDirectiveKind::Declare && isa(CurVarExpr)) - return VarExpr; + return CheckVarType(*this, CK, VarExpr, CurVarExpr); // Nothing really we can do here, as these are dependent. So just return they // are valid. if (isa(CurVarExpr) || (CK != OpenACCClauseKind::Reduction && isa(CurVarExpr))) - return VarExpr; + return CheckVarType(*this, CK, VarExpr, CurVarExpr); // There isn't really anything we can do in the case of a recovery expr, so // skip the diagnostic rather than produce a confusing diagnostic. diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index f3baf0c3ef3bc..5dd5b495480d9 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -245,7 +245,6 @@ void StandardConversionSequence::setAsIdentityConversion() { IsLvalueReference = true; BindsToFunctionLvalue = false; BindsToRvalue = false; - IsImplicitObjectArgumentQualificationConversion = false; BindsImplicitObjectArgumentWithoutRefQualifier = false; ObjCLifetimeConversionBinding = false; FromBracedInitList = false; @@ -5318,7 +5317,6 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, ICS.Standard.DirectBinding = BindsDirectly; ICS.Standard.IsLvalueReference = !isRValRef; ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType(); - ICS.Standard.IsImplicitObjectArgumentQualificationConversion = false; ICS.Standard.BindsToRvalue = InitCategory.isRValue(); ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; ICS.Standard.ObjCLifetimeConversionBinding = @@ -5498,7 +5496,6 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, ICS.Standard.IsLvalueReference = !isRValRef; ICS.Standard.BindsToFunctionLvalue = false; ICS.Standard.BindsToRvalue = true; - ICS.Standard.IsImplicitObjectArgumentQualificationConversion = false; ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; ICS.Standard.ObjCLifetimeConversionBinding = false; } else if (ICS.isUserDefined()) { @@ -5521,8 +5518,6 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, ICS.UserDefined.After.IsLvalueReference = !isRValRef; ICS.UserDefined.After.BindsToFunctionLvalue = false; ICS.UserDefined.After.BindsToRvalue = !LValRefType; - ICS.UserDefined.After.IsImplicitObjectArgumentQualificationConversion = - false; ICS.UserDefined.After.BindsImplicitObjectArgumentWithoutRefQualifier = false; ICS.UserDefined.After.ObjCLifetimeConversionBinding = false; ICS.UserDefined.After.FromBracedInitList = false; @@ -5807,7 +5802,6 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, StandardConversionSequence &SCS = Result.isStandard() ? Result.Standard : Result.UserDefined.After; SCS.ReferenceBinding = true; - SCS.IsImplicitObjectArgumentQualificationConversion = false; SCS.IsLvalueReference = ToType->isLValueReferenceType(); SCS.BindsToRvalue = true; SCS.BindsToFunctionLvalue = false; @@ -6005,12 +5999,8 @@ static ImplicitConversionSequence TryObjectArgumentInitialization( // affects the conversion rank. QualType ClassTypeCanon = S.Context.getCanonicalType(ClassType); ImplicitConversionKind SecondKind; - bool IsQualificationConversion = false; - if (ImplicitParamType.getCanonicalType() == FromTypeCanon) { + if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) { SecondKind = ICK_Identity; - } else if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) { - SecondKind = ICK_Identity; - IsQualificationConversion = true; } else if (S.IsDerivedFrom(Loc, FromType, ClassType)) { SecondKind = ICK_Derived_To_Base; } else if (!Method->isExplicitObjectMemberFunction()) { @@ -6051,8 +6041,6 @@ static ImplicitConversionSequence TryObjectArgumentInitialization( ICS.Standard.setFromType(FromType); ICS.Standard.setAllToTypes(ImplicitParamType); ICS.Standard.ReferenceBinding = true; - ICS.Standard.IsImplicitObjectArgumentQualificationConversion = - IsQualificationConversion; ICS.Standard.DirectBinding = true; ICS.Standard.IsLvalueReference = Method->getRefQualifier() != RQ_RValue; ICS.Standard.BindsToFunctionLvalue = false; @@ -11366,55 +11354,18 @@ OverloadingResult OverloadCandidateSet::BestViableFunction(Sema &S, DeferredCandidatesCount != 0 && !ResolutionByPerfectCandidateIsDisabled; if (TwoPhaseResolution) { - - PerfectViableFunction(S, Loc, Best); - if (Best != end()) - return ResultForBestCandidate(Best); + OverloadingResult Res = BestViableFunctionImpl(S, Loc, Best); + if (Best != end() && Best->isPerfectMatch(S.Context)) { + if (!(HasDeferredTemplateConstructors && + isa_and_nonnull(Best->Function))) + return Res; + } } InjectNonDeducedTemplateCandidates(S); return BestViableFunctionImpl(S, Loc, Best); } -void OverloadCandidateSet::PerfectViableFunction( - Sema &S, SourceLocation Loc, OverloadCandidateSet::iterator &Best) { - - Best = end(); - for (auto It = Candidates.begin(); It != Candidates.end(); ++It) { - - if (!It->isPerfectMatch(S.getASTContext())) - continue; - - // We found a suitable conversion function - // but if there is a template constructor in the target class - // we might prefer that instead. - if (HasDeferredTemplateConstructors && - isa_and_nonnull(It->Function)) { - Best = end(); - break; - } - - if (Best == end()) { - Best = It; - continue; - } - if (Best->Function && It->Function) { - FunctionDecl *D = - S.getMoreConstrainedFunction(Best->Function, It->Function); - if (D == nullptr) { - Best = end(); - break; - } - if (D == It->Function) - Best = It; - continue; - } - // ambiguous - Best = end(); - break; - } -} - OverloadingResult OverloadCandidateSet::BestViableFunctionImpl( Sema &S, SourceLocation Loc, OverloadCandidateSet::iterator &Best) { diff --git a/clang/lib/Sema/SemaRISCV.cpp b/clang/lib/Sema/SemaRISCV.cpp index 43f7992906c54..994cd07c1e263 100644 --- a/clang/lib/Sema/SemaRISCV.cpp +++ b/clang/lib/Sema/SemaRISCV.cpp @@ -1635,6 +1635,116 @@ bool SemaRISCV::isValidFMVExtension(StringRef Ext) { return -1 != RISCVISAInfo::getRISCVFeaturesBitsInfo(Ext).second; } +bool SemaRISCV::checkTargetVersionAttr(const StringRef Param, + const SourceLocation Loc) { + using namespace DiagAttrParams; + + llvm::SmallVector AttrStrs; + Param.split(AttrStrs, ';'); + + bool HasArch = false; + bool HasPriority = false; + bool HasDefault = false; + bool DuplicateAttr = false; + for (StringRef AttrStr : AttrStrs) { + AttrStr = AttrStr.trim(); + // Only support arch=+ext,... syntax. + if (AttrStr.starts_with("arch=+")) { + DuplicateAttr = HasArch; + HasArch = true; + ParsedTargetAttr TargetAttr = + getASTContext().getTargetInfo().parseTargetAttr(AttrStr); + + if (TargetAttr.Features.empty() || + llvm::any_of(TargetAttr.Features, [&](const StringRef Ext) { + return !isValidFMVExtension(Ext); + })) + return Diag(Loc, diag::warn_unsupported_target_attribute) + << Unsupported << None << AttrStr << TargetVersion; + } else if (AttrStr == "default") { + DuplicateAttr = HasDefault; + HasDefault = true; + } else if (AttrStr.consume_front("priority=")) { + DuplicateAttr = HasPriority; + HasPriority = true; + unsigned Digit; + if (AttrStr.getAsInteger(0, Digit)) + return Diag(Loc, diag::warn_unsupported_target_attribute) + << Unsupported << None << AttrStr << TargetVersion; + } else { + return Diag(Loc, diag::warn_unsupported_target_attribute) + << Unsupported << None << AttrStr << TargetVersion; + } + } + + if (((HasPriority || HasArch) && HasDefault) || DuplicateAttr || + (HasPriority && !HasArch)) + return Diag(Loc, diag::warn_unsupported_target_attribute) + << Unsupported << None << Param << TargetVersion; + + return false; +} + +bool SemaRISCV::checkTargetClonesAttr( + SmallVectorImpl &Params, SmallVectorImpl &Locs, + SmallVectorImpl> &NewParams) { + using namespace DiagAttrParams; + + assert(Params.size() == Locs.size() && + "Mismatch between number of string parameters and locations"); + + bool HasDefault = false; + for (unsigned I = 0, E = Params.size(); I < E; ++I) { + const StringRef Param = Params[I].trim(); + const SourceLocation &Loc = Locs[I]; + + llvm::SmallVector AttrStrs; + Param.split(AttrStrs, ';'); + + bool IsPriority = false; + bool IsDefault = false; + for (StringRef AttrStr : AttrStrs) { + AttrStr = AttrStr.trim(); + // Only support arch=+ext,... syntax. + if (AttrStr.starts_with("arch=+")) { + ParsedTargetAttr TargetAttr = + getASTContext().getTargetInfo().parseTargetAttr(AttrStr); + + if (TargetAttr.Features.empty() || + llvm::any_of(TargetAttr.Features, [&](const StringRef Ext) { + return !isValidFMVExtension(Ext); + })) + return Diag(Loc, diag::warn_unsupported_target_attribute) + << Unsupported << None << Param << TargetClones; + } else if (AttrStr == "default") { + IsDefault = true; + HasDefault = true; + } else if (AttrStr.consume_front("priority=")) { + IsPriority = true; + unsigned Digit; + if (AttrStr.getAsInteger(0, Digit)) + return Diag(Loc, diag::warn_unsupported_target_attribute) + << Unsupported << None << Param << TargetClones; + } else { + return Diag(Loc, diag::warn_unsupported_target_attribute) + << Unsupported << None << Param << TargetClones; + } + } + + if (IsPriority && IsDefault) + return Diag(Loc, diag::warn_unsupported_target_attribute) + << Unsupported << None << Param << TargetClones; + + if (llvm::is_contained(NewParams, Param)) + Diag(Loc, diag::warn_target_clone_duplicate_options); + NewParams.push_back(Param); + } + if (!HasDefault) + return Diag(Locs[0], diag::err_target_clone_must_have_default); + + return false; +} + SemaRISCV::SemaRISCV(Sema &S) : SemaBase(S) {} } // namespace clang diff --git a/clang/lib/Sema/SemaSPIRV.cpp b/clang/lib/Sema/SemaSPIRV.cpp index 76d3cff908b37..c8ea0d09c4081 100644 --- a/clang/lib/Sema/SemaSPIRV.cpp +++ b/clang/lib/Sema/SemaSPIRV.cpp @@ -46,6 +46,49 @@ static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall) { return false; } +static bool CheckAllArgTypesAreCorrect( + Sema *S, CallExpr *TheCall, + llvm::ArrayRef< + llvm::function_ref> + Checks) { + unsigned NumArgs = TheCall->getNumArgs(); + assert(Checks.size() == NumArgs && + "Wrong number of checks for Number of args."); + // Apply each check to the corresponding argument + for (unsigned I = 0; I < NumArgs; ++I) { + Expr *Arg = TheCall->getArg(I); + if (Checks[I](S, Arg->getBeginLoc(), I + 1, Arg->getType())) + return true; + } + return false; +} + +static bool CheckFloatOrHalfRepresentation(Sema *S, SourceLocation Loc, + int ArgOrdinal, + clang::QualType PassedType) { + clang::QualType BaseType = + PassedType->isVectorType() + ? PassedType->castAs()->getElementType() + : PassedType; + if (!BaseType->isHalfType() && !BaseType->isFloat16Type() && + !BaseType->isFloat32Type()) + return S->Diag(Loc, diag::err_builtin_invalid_arg_type) + << ArgOrdinal << /* scalar or vector of */ 5 << /* no int */ 0 + << /* half or float */ 2 << PassedType; + return false; +} + +static bool CheckFloatOrHalfScalarRepresentation(Sema *S, SourceLocation Loc, + int ArgOrdinal, + clang::QualType PassedType) { + if (!PassedType->isHalfType() && !PassedType->isFloat16Type() && + !PassedType->isFloat32Type()) + return S->Diag(Loc, diag::err_builtin_invalid_arg_type) + << ArgOrdinal << /* scalar */ 1 << /* no int */ 0 + << /* half or float */ 2 << PassedType; + return false; +} + static std::optional processConstant32BitIntArgument(Sema &SemaRef, CallExpr *Call, int Argument) { ExprResult Arg = @@ -235,6 +278,43 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(const TargetInfo &TI, TheCall->setType(RetTy); break; } + case SPIRV::BI__builtin_spirv_refract: { + if (SemaRef.checkArgCount(TheCall, 3)) + return true; + + llvm::function_ref + ChecksArr[] = {CheckFloatOrHalfRepresentation, + CheckFloatOrHalfRepresentation, + CheckFloatOrHalfScalarRepresentation}; + if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall, + llvm::ArrayRef(ChecksArr))) + return true; + // Check that first two arguments are vectors/scalars of the same type + QualType Arg0Type = TheCall->getArg(0)->getType(); + if (!SemaRef.getASTContext().hasSameUnqualifiedType( + Arg0Type, TheCall->getArg(1)->getType())) + return SemaRef.Diag(TheCall->getBeginLoc(), + diag::err_vec_builtin_incompatible_vector) + << TheCall->getDirectCallee() << /* first two */ 0 + << SourceRange(TheCall->getArg(0)->getBeginLoc(), + TheCall->getArg(1)->getEndLoc()); + + // Check that scalar type of 3rd arg is same as base type of first two args + clang::QualType BaseType = + Arg0Type->isVectorType() + ? Arg0Type->castAs()->getElementType() + : Arg0Type; + if (!SemaRef.getASTContext().hasSameUnqualifiedType( + BaseType, TheCall->getArg(2)->getType())) + return SemaRef.Diag(TheCall->getBeginLoc(), + diag::err_hlsl_builtin_scalar_vector_mismatch) + << /* all */ 0 << TheCall->getDirectCallee() << Arg0Type + << TheCall->getArg(2)->getType(); + + QualType RetTy = TheCall->getArg(0)->getType(); + TheCall->setType(RetTy); + break; + } case SPIRV::BI__builtin_spirv_smoothstep: { if (SemaRef.checkArgCount(TheCall, 3)) return true; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index b76619fc50268..698d1270be634 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -6299,7 +6299,6 @@ bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier( switch (NNS->getKind()) { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: case NestedNameSpecifier::Super: return false; diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index d09a72b71b805..e1a975bcfb3e1 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3083,8 +3083,7 @@ static TemplateDeductionResult ConvertDeducedTemplateArguments( // If there was no default argument, deduction is incomplete. if (DefArg.getArgument().isNull()) { - Info.Param = makeTemplateParameter( - const_cast(TemplateParams->getParam(I))); + Info.Param = makeTemplateParameter(TemplateParams->getParam(I)); Info.reset( TemplateArgumentList::CreateCopy(S.Context, CTAI.SugaredConverted), TemplateArgumentList::CreateCopy(S.Context, CTAI.CanonicalConverted)); @@ -3100,8 +3099,7 @@ static TemplateDeductionResult ConvertDeducedTemplateArguments( if (S.CheckTemplateArgument( Param, DefArg, TD, TD->getLocation(), TD->getSourceRange().getEnd(), /*ArgumentPackIndex=*/0, CTAI, Sema::CTAK_Specified)) { - Info.Param = makeTemplateParameter( - const_cast(TemplateParams->getParam(I))); + Info.Param = makeTemplateParameter(TemplateParams->getParam(I)); // FIXME: These template arguments are temporary. Free them! Info.reset( TemplateArgumentList::CreateCopy(S.Context, CTAI.SugaredConverted), @@ -3227,7 +3225,7 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction( if (ParamIdx >= TPL->size()) ParamIdx = TPL->size() - 1; - Decl *Param = const_cast(TPL->getParam(ParamIdx)); + Decl *Param = TPL->getParam(ParamIdx); Info.Param = makeTemplateParameter(Param); Info.FirstArg = Ps[ArgIdx].getArgument(); return TemplateDeductionResult::SubstitutionFailure; diff --git a/clang/lib/Sema/SemaX86.cpp b/clang/lib/Sema/SemaX86.cpp index 5c149bdec7073..850bcb17bece1 100644 --- a/clang/lib/Sema/SemaX86.cpp +++ b/clang/lib/Sema/SemaX86.cpp @@ -954,6 +954,11 @@ bool SemaX86::CheckBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, l = 0; u = 15; break; + case X86::BI__builtin_ia32_prefetchi: + i = 1; + l = 2; // _MM_HINT_T1 + u = 3; // _MM_HINT_T0 + break; } // Note that we don't force a hard error on the range check here, allowing @@ -1056,4 +1061,61 @@ void SemaX86::handleForceAlignArgPointerAttr(Decl *D, const ParsedAttr &AL) { X86ForceAlignArgPointerAttr(getASTContext(), AL)); } +bool SemaX86::checkTargetClonesAttr( + SmallVectorImpl &Params, SmallVectorImpl &Locs, + SmallVectorImpl> &NewParams) { + using namespace DiagAttrParams; + + assert(Params.size() == Locs.size() && + "Mismatch between number of string parameters and locations"); + + bool HasDefault = false; + bool HasComma = false; + for (unsigned I = 0, E = Params.size(); I < E; ++I) { + const StringRef Param = Params[I].trim(); + const SourceLocation &Loc = Locs[I]; + + if (Param.empty() || Param.ends_with(',')) + return Diag(Loc, diag::warn_unsupported_target_attribute) + << Unsupported << None << "" << TargetClones; + + if (Param.contains(',')) + HasComma = true; + + StringRef LHS; + StringRef RHS = Param; + do { + std::tie(LHS, RHS) = RHS.split(','); + LHS = LHS.trim(); + const SourceLocation &CurLoc = + Loc.getLocWithOffset(LHS.data() - Param.data()); + + if (LHS.starts_with("arch=")) { + if (!getASTContext().getTargetInfo().isValidCPUName( + LHS.drop_front(sizeof("arch=") - 1))) + return Diag(CurLoc, diag::warn_unsupported_target_attribute) + << Unsupported << CPU << LHS.drop_front(sizeof("arch=") - 1) + << TargetClones; + } else if (LHS == "default") + HasDefault = true; + else if (!getASTContext().getTargetInfo().isValidFeatureName(LHS) || + getASTContext().getTargetInfo().getFMVPriority(LHS) == 0) + return Diag(CurLoc, diag::warn_unsupported_target_attribute) + << Unsupported << None << LHS << TargetClones; + + if (llvm::is_contained(NewParams, LHS)) + Diag(CurLoc, diag::warn_target_clone_duplicate_options); + // Note: Add even if there are duplicates, since it changes name mangling. + NewParams.push_back(LHS); + } while (!RHS.empty()); + } + if (HasComma && Params.size() > 1) + Diag(Locs[0], diag::warn_target_clone_mixed_values); + + if (!HasDefault) + return Diag(Locs[0], diag::err_target_clone_must_have_default); + + return false; +} + } // namespace clang diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 3e38f8b183dfd..c7428d1a02345 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4621,22 +4621,12 @@ NestedNameSpecifierLoc TreeTransform::TransformNestedNameSpecifierLoc( } case NestedNameSpecifier::Namespace: { - NamespaceDecl *NS = - cast_or_null(getDerived().TransformDecl( - Q.getLocalBeginLoc(), QNNS->getAsNamespace())); + auto *NS = cast(getDerived().TransformDecl( + Q.getLocalBeginLoc(), QNNS->getAsNamespace())); SS.Extend(SemaRef.Context, NS, Q.getLocalBeginLoc(), Q.getLocalEndLoc()); break; } - case NestedNameSpecifier::NamespaceAlias: { - NamespaceAliasDecl *Alias = - cast_or_null(getDerived().TransformDecl( - Q.getLocalBeginLoc(), QNNS->getAsNamespaceAlias())); - SS.Extend(SemaRef.Context, Alias, Q.getLocalBeginLoc(), - Q.getLocalEndLoc()); - break; - } - case NestedNameSpecifier::Global: // There is no meaningful transformation that one could perform on the // global scope. @@ -7255,6 +7245,12 @@ QualType TreeTransform::TransformDependentBitIntType( return Result; } +template +QualType TreeTransform::TransformPredefinedSugarType( + TypeLocBuilder &TLB, PredefinedSugarTypeLoc TL) { + llvm_unreachable("This type does not need to be transformed."); +} + /// Simple iterator that traverses the template arguments in a /// container that provides a \c getArgLoc() member function. /// diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index d0bb7fb1d06ad..10aedb68fcd9d 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -7574,11 +7574,16 @@ void TypeLocReader::VisitPipeTypeLoc(PipeTypeLoc TL) { void TypeLocReader::VisitBitIntTypeLoc(clang::BitIntTypeLoc TL) { TL.setNameLoc(readSourceLocation()); } + void TypeLocReader::VisitDependentBitIntTypeLoc( clang::DependentBitIntTypeLoc TL) { TL.setNameLoc(readSourceLocation()); } +void TypeLocReader::VisitPredefinedSugarTypeLoc(PredefinedSugarTypeLoc TL) { + // Nothing to do. +} + void ASTRecordReader::readTypeLoc(TypeLoc TL) { TypeLocReader TLR(*this); for (; !TL.isNull(); TL = TL.getNextTypeLoc()) @@ -10107,19 +10112,12 @@ ASTRecordReader::readNestedNameSpecifierLoc() { } case NestedNameSpecifier::Namespace: { - NamespaceDecl *NS = readDeclAs(); + auto *NS = readDeclAs(); SourceRange Range = readSourceRange(); Builder.Extend(Context, NS, Range.getBegin(), Range.getEnd()); break; } - case NestedNameSpecifier::NamespaceAlias: { - NamespaceAliasDecl *Alias = readDeclAs(); - SourceRange Range = readSourceRange(); - Builder.Extend(Context, Alias, Range.getBegin(), Range.getEnd()); - break; - } - case NestedNameSpecifier::TypeSpec: { TypeSourceInfo *T = readTypeSourceInfo(); if (!T) diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index b918bfbd549c3..bd84a9741d01b 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1889,7 +1889,7 @@ void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { D->NamespaceLoc = readSourceLocation(); D->IdentLoc = readSourceLocation(); D->QualifierLoc = Record.readNestedNameSpecifierLoc(); - D->Namespace = readDeclAs(); + D->Namespace = readDeclAs(); mergeRedeclarable(D, Redecl); } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 847283e9842e5..a6957e54b66f1 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -692,7 +692,6 @@ void TypeLocWriter::VisitAtomicTypeLoc(AtomicTypeLoc TL) { void TypeLocWriter::VisitPipeTypeLoc(PipeTypeLoc TL) { addSourceLocation(TL.getKWLoc()); } - void TypeLocWriter::VisitBitIntTypeLoc(clang::BitIntTypeLoc TL) { addSourceLocation(TL.getNameLoc()); } @@ -701,6 +700,11 @@ void TypeLocWriter::VisitDependentBitIntTypeLoc( addSourceLocation(TL.getNameLoc()); } +void TypeLocWriter::VisitPredefinedSugarTypeLoc( + clang::PredefinedSugarTypeLoc TL) { + // Nothing to do. +} + void ASTWriter::WriteTypeAbbrevs() { using namespace llvm; @@ -7093,11 +7097,6 @@ void ASTRecordWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { AddSourceRange(NNS.getLocalSourceRange()); break; - case NestedNameSpecifier::NamespaceAlias: - AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespaceAlias()); - AddSourceRange(NNS.getLocalSourceRange()); - break; - case NestedNameSpecifier::TypeSpec: AddTypeRef(NNS.getTypeLoc().getType()); AddTypeLoc(NNS.getTypeLoc()); diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 30a04977d906d..68efdbaec341b 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -1281,7 +1281,7 @@ SVal MallocChecker::evalMulForBufferSize(CheckerContext &C, const Expr *Blocks, SVal BlockBytesVal = C.getSVal(BlockBytes); ProgramStateRef State = C.getState(); SVal TotalSize = SB.evalBinOp(State, BO_Mul, BlocksVal, BlockBytesVal, - SB.getContext().getSizeType()); + SB.getContext().getCanonicalSizeType()); return TotalSize; } @@ -1311,11 +1311,9 @@ static bool isStandardRealloc(const CallEvent &Call) { const FunctionDecl *FD = dyn_cast(Call.getDecl()); assert(FD); ASTContext &AC = FD->getASTContext(); - - return FD->getDeclaredReturnType().getDesugaredType(AC) == AC.VoidPtrTy && - FD->getParamDecl(0)->getType().getDesugaredType(AC) == AC.VoidPtrTy && - FD->getParamDecl(1)->getType().getDesugaredType(AC) == - AC.getSizeType(); + return AC.hasSameType(FD->getDeclaredReturnType(), AC.VoidPtrTy) && + AC.hasSameType(FD->getParamDecl(0)->getType(), AC.VoidPtrTy) && + AC.hasSameType(FD->getParamDecl(1)->getType(), AC.getSizeType()); } static bool isGRealloc(const CallEvent &Call) { @@ -1323,10 +1321,9 @@ static bool isGRealloc(const CallEvent &Call) { assert(FD); ASTContext &AC = FD->getASTContext(); - return FD->getDeclaredReturnType().getDesugaredType(AC) == AC.VoidPtrTy && - FD->getParamDecl(0)->getType().getDesugaredType(AC) == AC.VoidPtrTy && - FD->getParamDecl(1)->getType().getDesugaredType(AC) == - AC.UnsignedLongTy; + return AC.hasSameType(FD->getDeclaredReturnType(), AC.VoidPtrTy) && + AC.hasSameType(FD->getParamDecl(0)->getType(), AC.VoidPtrTy) && + AC.hasSameType(FD->getParamDecl(1)->getType(), AC.UnsignedLongTy); } void MallocChecker::checkRealloc(ProgramStateRef State, const CallEvent &Call, @@ -2830,10 +2827,10 @@ MallocChecker::ReallocMemAux(CheckerContext &C, const CallEvent &Call, return nullptr; // Compare the size argument to 0. - DefinedOrUnknownSVal SizeZero = - svalBuilder.evalEQ(State, TotalSize.castAs(), - svalBuilder.makeIntValWithWidth( - svalBuilder.getContext().getSizeType(), 0)); + DefinedOrUnknownSVal SizeZero = svalBuilder.evalEQ( + State, TotalSize.castAs(), + svalBuilder.makeIntValWithWidth( + svalBuilder.getContext().getCanonicalSizeType(), 0)); ProgramStateRef StatePtrIsNull, StatePtrNotNull; std::tie(StatePtrIsNull, StatePtrNotNull) = State->assume(PtrEQ); diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp index 1c748f9bc1828..52b3d1e95942c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp @@ -1666,7 +1666,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( const QualType IntTy = ACtx.IntTy; const QualType UnsignedIntTy = ACtx.UnsignedIntTy; const QualType LongTy = ACtx.LongTy; - const QualType SizeTy = ACtx.getSizeType(); + const QualType SizeTyCanonTy = ACtx.getCanonicalSizeType(); const QualType VoidPtrTy = getPointerTy(VoidTy); // void * const QualType IntPtrTy = getPointerTy(IntTy); // int * @@ -1684,14 +1684,14 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( const QualType ConstWchar_tPtrTy = getPointerTy(getConstTy(WCharTy)); // const wchar_t * const QualType ConstVoidPtrRestrictTy = getRestrictTy(ConstVoidPtrTy); - const QualType SizePtrTy = getPointerTy(SizeTy); + const QualType SizePtrTy = getPointerTy(SizeTyCanonTy); const QualType SizePtrRestrictTy = getRestrictTy(SizePtrTy); const RangeInt IntMax = BVF.getMaxValue(IntTy)->getLimitedValue(); const RangeInt UnsignedIntMax = BVF.getMaxValue(UnsignedIntTy)->getLimitedValue(); const RangeInt LongMax = BVF.getMaxValue(LongTy)->getLimitedValue(); - const RangeInt SizeMax = BVF.getMaxValue(SizeTy)->getLimitedValue(); + const RangeInt SizeMax = BVF.getMaxValue(SizeTyCanonTy)->getLimitedValue(); // Set UCharRangeMax to min of int or uchar maximum value. // The C standard states that the arguments of functions like isalpha must @@ -2057,18 +2057,19 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( // size_t fread(void *restrict ptr, size_t size, size_t nitems, // FILE *restrict stream); - addToFunctionSummaryMap( - "fread", - Signature(ArgTypes{VoidPtrRestrictTy, SizeTy, SizeTy, FilePtrRestrictTy}, - RetType{SizeTy}), - FreadSummary); + addToFunctionSummaryMap("fread", + Signature(ArgTypes{VoidPtrRestrictTy, SizeTyCanonTy, + SizeTyCanonTy, FilePtrRestrictTy}, + RetType{SizeTyCanonTy}), + FreadSummary); // size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, // FILE *restrict stream); - addToFunctionSummaryMap("fwrite", - Signature(ArgTypes{ConstVoidPtrRestrictTy, SizeTy, - SizeTy, FilePtrRestrictTy}, - RetType{SizeTy}), - FreadSummary); + addToFunctionSummaryMap( + "fwrite", + Signature(ArgTypes{ConstVoidPtrRestrictTy, SizeTyCanonTy, SizeTyCanonTy, + FilePtrRestrictTy}, + RetType{SizeTyCanonTy}), + FreadSummary); std::optional Ssize_tTy = lookupTy("ssize_t"); std::optional Ssize_tMax = getMaxValue(Ssize_tTy); @@ -2083,12 +2084,14 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( // should handle them together with the rest of the POSIX functions. // ssize_t read(int fildes, void *buf, size_t nbyte); addToFunctionSummaryMap( - "read", Signature(ArgTypes{IntTy, VoidPtrTy, SizeTy}, RetType{Ssize_tTy}), + "read", + Signature(ArgTypes{IntTy, VoidPtrTy, SizeTyCanonTy}, RetType{Ssize_tTy}), ReadSummary); // ssize_t write(int fildes, const void *buf, size_t nbyte); addToFunctionSummaryMap( "write", - Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy}, RetType{Ssize_tTy}), + Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTyCanonTy}, + RetType{Ssize_tTy}), ReadSummary); auto GetLineSummary = @@ -2618,7 +2621,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( // char *strndup(const char *s, size_t n); addToFunctionSummaryMap( "strndup", - Signature(ArgTypes{ConstCharPtrTy, SizeTy}, RetType{CharPtrTy}), + Signature(ArgTypes{ConstCharPtrTy, SizeTyCanonTy}, RetType{CharPtrTy}), Summary(NoEvalCall) .ArgConstraint(NotNull(ArgNo(0))) .ArgConstraint( @@ -2649,7 +2652,8 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( // char *getcwd(char *buf, size_t size); addToFunctionSummaryMap( - "getcwd", Signature(ArgTypes{CharPtrTy, SizeTy}, RetType{CharPtrTy}), + "getcwd", + Signature(ArgTypes{CharPtrTy, SizeTyCanonTy}, RetType{CharPtrTy}), Summary(NoEvalCall) .Case({NotNull(0), ArgumentCondition(1, WithinRange, Range(1, SizeMax)), @@ -2957,8 +2961,9 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( // FIXME: Improve for errno modeling. addToFunctionSummaryMap( "mmap", - Signature(ArgTypes{VoidPtrTy, SizeTy, IntTy, IntTy, IntTy, Off_tTy}, - RetType{VoidPtrTy}), + Signature( + ArgTypes{VoidPtrTy, SizeTyCanonTy, IntTy, IntTy, IntTy, Off_tTy}, + RetType{VoidPtrTy}), Summary(NoEvalCall) .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, SizeMax))) .ArgConstraint( @@ -2970,8 +2975,9 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( // FIXME: Improve for errno modeling. addToFunctionSummaryMap( "mmap64", - Signature(ArgTypes{VoidPtrTy, SizeTy, IntTy, IntTy, IntTy, Off64_tTy}, - RetType{VoidPtrTy}), + Signature( + ArgTypes{VoidPtrTy, SizeTyCanonTy, IntTy, IntTy, IntTy, Off64_tTy}, + RetType{VoidPtrTy}), Summary(NoEvalCall) .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, SizeMax))) .ArgConstraint( @@ -3002,8 +3008,9 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( // size_t bufsize); addToFunctionSummaryMap( "readlink", - Signature(ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy}, - RetType{Ssize_tTy}), + Signature( + ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTyCanonTy}, + RetType{Ssize_tTy}), Summary(NoEvalCall) .Case({ArgumentCondition(2, WithinRange, Range(1, IntMax)), ReturnValueCondition(LessThanOrEq, ArgNo(2)), @@ -3025,9 +3032,9 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( // char *restrict buf, size_t bufsize); addToFunctionSummaryMap( "readlinkat", - Signature( - ArgTypes{IntTy, ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy}, - RetType{Ssize_tTy}), + Signature(ArgTypes{IntTy, ConstCharPtrRestrictTy, CharPtrRestrictTy, + SizeTyCanonTy}, + RetType{Ssize_tTy}), Summary(NoEvalCall) .Case({ArgumentCondition(3, WithinRange, Range(1, IntMax)), ReturnValueCondition(LessThanOrEq, ArgNo(3)), @@ -3268,14 +3275,14 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( // size_t length, // int flags, struct sockaddr *restrict address, // socklen_t *restrict address_len); - Signature(ArgTypes{IntTy, VoidPtrRestrictTy, SizeTy, IntTy, + Signature(ArgTypes{IntTy, VoidPtrRestrictTy, SizeTyCanonTy, IntTy, StructSockaddrPtrRestrictTy, Socklen_tPtrRestrictTy}, RetType{Ssize_tTy}), Recvfrom)) addToFunctionSummaryMap( "recvfrom", - Signature(ArgTypes{IntTy, VoidPtrRestrictTy, SizeTy, IntTy, + Signature(ArgTypes{IntTy, VoidPtrRestrictTy, SizeTyCanonTy, IntTy, Irrelevant, Socklen_tPtrRestrictTy}, RetType{Ssize_tTy}), Recvfrom); @@ -3297,14 +3304,14 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( // ssize_t sendto(int socket, const void *message, size_t length, // int flags, const struct sockaddr *dest_addr, // socklen_t dest_len); - Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy, + Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTyCanonTy, IntTy, ConstStructSockaddrPtrTy, Socklen_tTy}, RetType{Ssize_tTy}), Sendto)) addToFunctionSummaryMap( "sendto", - Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy, Irrelevant, - Socklen_tTy}, + Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTyCanonTy, IntTy, + Irrelevant, Socklen_tTy}, RetType{Ssize_tTy}), Sendto); @@ -3320,7 +3327,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( // ssize_t recv(int sockfd, void *buf, size_t len, int flags); addToFunctionSummaryMap( "recv", - Signature(ArgTypes{IntTy, VoidPtrTy, SizeTy, IntTy}, + Signature(ArgTypes{IntTy, VoidPtrTy, SizeTyCanonTy, IntTy}, RetType{Ssize_tTy}), Summary(NoEvalCall) .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), @@ -3395,7 +3402,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( // ssize_t send(int sockfd, const void *buf, size_t len, int flags); addToFunctionSummaryMap( "send", - Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy}, + Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTyCanonTy, IntTy}, RetType{Ssize_tTy}), Summary(NoEvalCall) .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), @@ -3683,7 +3690,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( // int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize); addToFunctionSummaryMap( {"pthread_attr_setstacksize", "pthread_attr_setguardsize"}, - Signature(ArgTypes{Pthread_attr_tPtrTy, SizeTy}, RetType{IntTy}), + Signature(ArgTypes{Pthread_attr_tPtrTy, SizeTyCanonTy}, RetType{IntTy}), Summary(NoEvalCall) .ArgConstraint(NotNull(ArgNo(0))) .ArgConstraint( @@ -3888,13 +3895,14 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( .ArgConstraint(NotNull(ArgNo(1)))); addToFunctionSummaryMap( "__buf_size_arg_constraint", - Signature(ArgTypes{ConstVoidPtrTy, SizeTy}, RetType{IntTy}), + Signature(ArgTypes{ConstVoidPtrTy, SizeTyCanonTy}, RetType{IntTy}), Summary(EvalCallAsPure) .ArgConstraint( BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1)))); addToFunctionSummaryMap( "__buf_size_arg_constraint_mul", - Signature(ArgTypes{ConstVoidPtrTy, SizeTy, SizeTy}, RetType{IntTy}), + Signature(ArgTypes{ConstVoidPtrTy, SizeTyCanonTy, SizeTyCanonTy}, + RetType{IntTy}), Summary(EvalCallAsPure) .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1), /*BufSizeMultiplier=*/ArgNo(2)))); diff --git a/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp index 1042b43680fd2..c97341f072aba 100644 --- a/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp @@ -92,7 +92,7 @@ ProgramStateRef VLASizeChecker::checkVLA(CheckerContext &C, ASTContext &Ctx = C.getASTContext(); SValBuilder &SVB = C.getSValBuilder(); - CanQualType SizeTy = Ctx.getSizeType(); + QualType SizeTy = Ctx.getSizeType(); uint64_t SizeMax = SVB.getBasicValueFactory().getMaxValue(SizeTy)->getZExtValue(); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index c77ef26da568d..d87484470f8b5 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1941,7 +1941,6 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::ConceptSpecializationExprClass: case Stmt::CXXRewrittenBinaryOperatorClass: case Stmt::RequiresExprClass: - case Expr::CXXParenListInitExprClass: case Stmt::EmbedExprClass: // Fall through. @@ -2315,11 +2314,22 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, break; } - case Stmt::InitListExprClass: + case Stmt::InitListExprClass: { + const InitListExpr *E = cast(S); Bldr.takeNodes(Pred); - VisitInitListExpr(cast(S), Pred, Dst); + ConstructInitList(E, E->inits(), E->isTransparent(), Pred, Dst); Bldr.addNodes(Dst); break; + } + + case Expr::CXXParenListInitExprClass: { + const CXXParenListInitExpr *E = cast(S); + Bldr.takeNodes(Pred); + ConstructInitList(E, E->getInitExprs(), /*IsTransparent*/ false, Pred, + Dst); + Bldr.addNodes(Dst); + break; + } case Stmt::MemberExprClass: Bldr.takeNodes(Pred); @@ -4114,3 +4124,33 @@ void *ProgramStateTrait::GDMIndex() { } void ExprEngine::anchor() { } + +void ExprEngine::ConstructInitList(const Expr *E, ArrayRef Args, + bool IsTransparent, ExplodedNode *Pred, + ExplodedNodeSet &Dst) { + assert((isa(E))); + + const LocationContext *LC = Pred->getLocationContext(); + + StmtNodeBuilder B(Pred, Dst, *currBldrCtx); + ProgramStateRef S = Pred->getState(); + QualType T = E->getType().getCanonicalType(); + + bool IsCompound = T->isArrayType() || T->isRecordType() || + T->isAnyComplexType() || T->isVectorType(); + + if (Args.size() > 1 || (E->isPRValue() && IsCompound && !IsTransparent)) { + llvm::ImmutableList ArgList = getBasicVals().getEmptySValList(); + for (Expr *E : llvm::reverse(Args)) + ArgList = getBasicVals().prependSVal(S->getSVal(E, LC), ArgList); + + B.generateNode(E, Pred, + S->BindExpr(E, LC, svalBuilder.makeCompoundVal(T, ArgList))); + } else { + B.generateNode(E, Pred, + S->BindExpr(E, LC, + Args.size() == 0 + ? getSValBuilder().makeZeroVal(T) + : S->getSVal(Args.front(), LC))); + } +} diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index fa8e669b6bb2f..f1a25a750dd0d 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -771,54 +771,6 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X)); } -void ExprEngine::VisitInitListExpr(const InitListExpr *IE, - ExplodedNode *Pred, - ExplodedNodeSet &Dst) { - StmtNodeBuilder B(Pred, Dst, *currBldrCtx); - - ProgramStateRef state = Pred->getState(); - const LocationContext *LCtx = Pred->getLocationContext(); - QualType T = getContext().getCanonicalType(IE->getType()); - unsigned NumInitElements = IE->getNumInits(); - - if (!IE->isGLValue() && !IE->isTransparent() && - (T->isArrayType() || T->isRecordType() || T->isVectorType() || - T->isAnyComplexType())) { - llvm::ImmutableList vals = getBasicVals().getEmptySValList(); - - // Handle base case where the initializer has no elements. - // e.g: static int* myArray[] = {}; - if (NumInitElements == 0) { - SVal V = svalBuilder.makeCompoundVal(T, vals); - B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); - return; - } - - for (const Stmt *S : llvm::reverse(*IE)) { - SVal V = state->getSVal(cast(S), LCtx); - vals = getBasicVals().prependSVal(V, vals); - } - - B.generateNode(IE, Pred, - state->BindExpr(IE, LCtx, - svalBuilder.makeCompoundVal(T, vals))); - return; - } - - // Handle scalars: int{5} and int{} and GLvalues. - // Note, if the InitListExpr is a GLvalue, it means that there is an address - // representing it, so it must have a single init element. - assert(NumInitElements <= 1); - - SVal V; - if (NumInitElements == 0) - V = getSValBuilder().makeZeroVal(T); - else - V = state->getSVal(IE->getInit(0), LCtx); - - B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); -} - void ExprEngine::VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R, diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index 9bd85479d9810..8ce2706cb1062 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -24,7 +24,6 @@ #include "clang/Tooling/DependencyScanning/DependencyScanningService.h" #include "clang/Tooling/DependencyScanning/InProcessModuleCache.h" #include "clang/Tooling/DependencyScanning/ModuleDepCollector.h" -#include "clang/Tooling/Tooling.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Error.h" @@ -376,25 +375,23 @@ class ScanningDependencyDirectivesGetter : public DependencyDirectivesGetter { /// A clang tool that runs the preprocessor in a mode that's optimized for /// dependency scanning for the given compiler invocation. -class DependencyScanningAction : public tooling::ToolAction { +class DependencyScanningAction { public: DependencyScanningAction( DependencyScanningService &Service, StringRef WorkingDirectory, DependencyConsumer &Consumer, DependencyActionController &Controller, llvm::IntrusiveRefCntPtr DepFS, - bool DisableFree, std::optional ModuleName = std::nullopt) + std::optional ModuleName = std::nullopt) : Service(Service), WorkingDirectory(WorkingDirectory), Consumer(Consumer), Controller(Controller), DepFS(std::move(DepFS)), - DisableFree(DisableFree), ModuleName(ModuleName) {} + ModuleName(ModuleName) {} bool runInvocation(std::shared_ptr Invocation, - FileManager *DriverFileMgr, + IntrusiveRefCntPtr FS, std::shared_ptr PCHContainerOps, - DiagnosticConsumer *DiagConsumer) override { + DiagnosticConsumer *DiagConsumer) { // Make a deep copy of the original Clang invocation. CompilerInvocation OriginalInvocation(*Invocation); - // Restore the value of DisableFree, which may be modified by Tooling. - OriginalInvocation.getFrontendOpts().DisableFree = DisableFree; if (any(Service.getOptimizeArgs() & ScanningOptimizations::Macros)) canonicalizeDefines(OriginalInvocation.getPreprocessorOpts()); @@ -419,8 +416,8 @@ class DependencyScanningAction : public tooling::ToolAction { // Create the compiler's actual diagnostics engine. sanitizeDiagOpts(ScanInstance.getDiagnosticOpts()); assert(!DiagConsumerFinished && "attempt to reuse finished consumer"); - ScanInstance.createDiagnostics(DriverFileMgr->getVirtualFileSystem(), - DiagConsumer, /*ShouldOwnClient=*/false); + ScanInstance.createDiagnostics(*FS, DiagConsumer, + /*ShouldOwnClient=*/false); if (!ScanInstance.hasDiagnostics()) return false; @@ -431,6 +428,7 @@ class DependencyScanningAction : public tooling::ToolAction { ScanInstance.getHeaderSearchOpts().BuildSessionTimestamp = Service.getBuildSessionTimestamp(); + ScanInstance.getFrontendOpts().DisableFree = false; ScanInstance.getFrontendOpts().GenerateGlobalModuleIndex = false; ScanInstance.getFrontendOpts().UseGlobalModuleIndex = false; // This will prevent us compiling individual modules asynchronously since @@ -441,9 +439,9 @@ class DependencyScanningAction : public tooling::ToolAction { any(Service.getOptimizeArgs() & ScanningOptimizations::VFS); // Support for virtual file system overlays. - auto FS = createVFSFromCompilerInvocation( - ScanInstance.getInvocation(), ScanInstance.getDiagnostics(), - DriverFileMgr->getVirtualFileSystemPtr()); + FS = createVFSFromCompilerInvocation(ScanInstance.getInvocation(), + ScanInstance.getDiagnostics(), + std::move(FS)); // Create a new FileManager to match the invocation's FileSystemOptions. auto *FileMgr = ScanInstance.createFileManager(FS); @@ -554,9 +552,6 @@ class DependencyScanningAction : public tooling::ToolAction { if (Result) setLastCC1Arguments(std::move(OriginalInvocation)); - // Propagate the statistics to the parent FileManager. - DriverFileMgr->AddStats(ScanInstance.getFileManager()); - return Result; } @@ -584,7 +579,6 @@ class DependencyScanningAction : public tooling::ToolAction { DependencyConsumer &Consumer; DependencyActionController &Controller; llvm::IntrusiveRefCntPtr DepFS; - bool DisableFree; std::optional ModuleName; std::optional ScanInstanceStorage; std::shared_ptr MDC; @@ -669,15 +663,14 @@ llvm::Error DependencyScanningWorker::computeDependencies( } static bool forEachDriverJob( - ArrayRef ArgStrs, DiagnosticsEngine &Diags, FileManager &FM, + ArrayRef ArgStrs, DiagnosticsEngine &Diags, + IntrusiveRefCntPtr FS, llvm::function_ref Callback) { SmallVector Argv; Argv.reserve(ArgStrs.size()); for (const std::string &Arg : ArgStrs) Argv.push_back(Arg.c_str()); - llvm::vfs::FileSystem *FS = &FM.getVirtualFileSystem(); - std::unique_ptr Driver = std::make_unique( Argv[0], llvm::sys::getDefaultTargetTriple(), Diags, "clang LLVM compiler", FS); @@ -687,7 +680,8 @@ static bool forEachDriverJob( bool CLMode = driver::IsClangCL( driver::getDriverMode(Argv[0], ArrayRef(Argv).slice(1))); - if (llvm::Error E = driver::expandResponseFiles(Argv, CLMode, Alloc, FS)) { + if (llvm::Error E = + driver::expandResponseFiles(Argv, CLMode, Alloc, FS.get())) { Diags.Report(diag::err_drv_expand_response_file) << llvm::toString(std::move(E)); return false; @@ -710,17 +704,25 @@ static bool forEachDriverJob( static bool createAndRunToolInvocation( std::vector CommandLine, DependencyScanningAction &Action, - FileManager &FM, + IntrusiveRefCntPtr FS, std::shared_ptr &PCHContainerOps, DiagnosticsEngine &Diags, DependencyConsumer &Consumer) { // Save executable path before providing CommandLine to ToolInvocation std::string Executable = CommandLine[0]; - ToolInvocation Invocation(std::move(CommandLine), &Action, &FM, - PCHContainerOps); - Invocation.setDiagnosticConsumer(Diags.getClient()); - Invocation.setDiagnosticOptions(&Diags.getDiagnosticOptions()); - if (!Invocation.run()) + + llvm::opt::ArgStringList Argv; + for (const std::string &Str : ArrayRef(CommandLine).drop_front()) + Argv.push_back(Str.c_str()); + + auto Invocation = std::make_shared(); + if (!CompilerInvocation::CreateFromArgs(*Invocation, Argv, Diags)) { + // FIXME: Should we just go on like cc1_main does? + return false; + } + + if (!Action.runInvocation(std::move(Invocation), std::move(FS), + PCHContainerOps, Diags.getClient())) return false; std::vector Args = Action.takeLastCC1Arguments(); @@ -733,37 +735,24 @@ bool DependencyScanningWorker::scanDependencies( DependencyConsumer &Consumer, DependencyActionController &Controller, DiagnosticConsumer &DC, llvm::IntrusiveRefCntPtr FS, std::optional ModuleName) { - auto FileMgr = - llvm::makeIntrusiveRefCnt(FileSystemOptions{}, FS); - std::vector CCommandLine(CommandLine.size(), nullptr); llvm::transform(CommandLine, CCommandLine.begin(), [](const std::string &Str) { return Str.c_str(); }); auto DiagOpts = CreateAndPopulateDiagOpts(CCommandLine); sanitizeDiagOpts(*DiagOpts); - IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(FileMgr->getVirtualFileSystem(), - *DiagOpts, &DC, - /*ShouldOwnClient=*/false); - - // Although `Diagnostics` are used only for command-line parsing, the - // custom `DiagConsumer` might expect a `SourceManager` to be present. - SourceManager SrcMgr(*Diags, *FileMgr); - Diags->setSourceManager(&SrcMgr); - // DisableFree is modified by Tooling for running - // in-process; preserve the original value, which is - // always true for a driver invocation. - bool DisableFree = true; + auto Diags = CompilerInstance::createDiagnostics(*FS, *DiagOpts, &DC, + /*ShouldOwnClient=*/false); + DependencyScanningAction Action(Service, WorkingDirectory, Consumer, - Controller, DepFS, DisableFree, ModuleName); + Controller, DepFS, ModuleName); bool Success = false; if (CommandLine[1] == "-cc1") { - Success = createAndRunToolInvocation(CommandLine, Action, *FileMgr, + Success = createAndRunToolInvocation(CommandLine, Action, FS, PCHContainerOps, *Diags, Consumer); } else { Success = forEachDriverJob( - CommandLine, *Diags, *FileMgr, [&](const driver::Command &Cmd) { + CommandLine, *Diags, FS, [&](const driver::Command &Cmd) { if (StringRef(Cmd.getCreator().getName()) != "clang") { // Non-clang command. Just pass through to the dependency // consumer. @@ -782,7 +771,7 @@ bool DependencyScanningWorker::scanDependencies( // system to ensure that any file system requests that // are made by the driver do not go through the // dependency scanning filesystem. - return createAndRunToolInvocation(std::move(Argv), Action, *FileMgr, + return createAndRunToolInvocation(std::move(Argv), Action, FS, PCHContainerOps, *Diags, Consumer); }); } diff --git a/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp b/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp index 9f10ee1c0d3f8..2b5a293b35841 100644 --- a/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp +++ b/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp @@ -285,8 +285,7 @@ HeaderIncludes::HeaderIncludes(StringRef FileName, StringRef Code, MaxInsertOffset(MinInsertOffset + getMaxHeaderInsertionOffset( FileName, Code.drop_front(MinInsertOffset), Style)), - MainIncludeFound(false), - Categories(Style, FileName) { + MainIncludeFound(false), Categories(Style, FileName) { // Add 0 for main header and INT_MAX for headers that are not in any // category. Priorities = {0, INT_MAX}; diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp index b88e6db7cceb7..807a8d8a34ad7 100644 --- a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp +++ b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp @@ -131,7 +131,7 @@ static int initialize(Lang Language) { Mapping->SymbolNames[SymIndex] = { QName.data(), NSLen, static_cast(QName.size() - NSLen)}; if (!HeaderName.empty()) - Mapping->SymbolHeaderIDs[SymIndex].push_back(AddHeader(HeaderName)); + Mapping->SymbolHeaderIDs[SymIndex].push_back(AddHeader(HeaderName)); NSSymbolMap &NSSymbols = AddNS(QName.take_front(NSLen)); NSSymbols.try_emplace(QName.drop_front(NSLen), SymIndex); @@ -236,7 +236,7 @@ std::optional Symbol::named(llvm::StringRef Scope, llvm::StringRef Name, return std::nullopt; } std::optional
Symbol::header() const { - const auto& Headers = getMappingPerLang(Language)->SymbolHeaderIDs[ID]; + const auto &Headers = getMappingPerLang(Language)->SymbolHeaderIDs[ID]; if (Headers.empty()) return std::nullopt; return Header(Headers.front(), Language); diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index caac719caf8e8..eb9fa7a7fa1e8 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -950,7 +950,6 @@ class BuildTreeVisitor : public RecursiveASTVisitor { case NestedNameSpecifier::Global: return syntax::NodeKind::GlobalNameSpecifier; case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Identifier: return syntax::NodeKind::IdentifierNameSpecifier; case NestedNameSpecifier::TypeSpec: { diff --git a/clang/test/AST/ByteCode/builtin-bit-cast.cpp b/clang/test/AST/ByteCode/builtin-bit-cast.cpp index 3c5e89d7d5a74..bc356b0b6e122 100644 --- a/clang/test/AST/ByteCode/builtin-bit-cast.cpp +++ b/clang/test/AST/ByteCode/builtin-bit-cast.cpp @@ -22,6 +22,10 @@ typedef __INTPTR_TYPE__ intptr_t; static_assert(sizeof(int) == 4); static_assert(sizeof(long long) == 8); + +constexpr bool test_bad_bool = __builtin_bit_cast(bool, (char)0xff); // both-error {{must be initialized by a constant expression}} \ + // both-note {{value 255 cannot be represented in type 'bool'}} + template constexpr To bit_cast(const From &from) { static_assert(sizeof(To) == sizeof(From)); diff --git a/clang/test/AST/ByteCode/builtin-constant-p.cpp b/clang/test/AST/ByteCode/builtin-constant-p.cpp index 9f5521590833d..315a907949c34 100644 --- a/clang/test/AST/ByteCode/builtin-constant-p.cpp +++ b/clang/test/AST/ByteCode/builtin-constant-p.cpp @@ -140,3 +140,11 @@ void test17(void) { F("string literal" + 1); // both-warning {{adding}} \ // both-note {{use array indexing}} } + +/// FIXME +static void foo(int i) __attribute__((__diagnose_if__(!__builtin_constant_p(i), "not constant", "error"))) // expected-note {{from}} +{ +} +static void bar(int i) { + foo(15); // expected-error {{not constant}} +} diff --git a/clang/test/AST/ByteCode/complex.cpp b/clang/test/AST/ByteCode/complex.cpp index 2c0111c53d3bf..be10b3cfa53da 100644 --- a/clang/test/AST/ByteCode/complex.cpp +++ b/clang/test/AST/ByteCode/complex.cpp @@ -396,10 +396,9 @@ namespace ComplexConstexpr { // both-note {{cannot refer to element 3 of array of 2 elements}} constexpr _Complex float *p = 0; constexpr float pr = __real *p; // both-error {{constant expr}} \ - // ref-note {{cannot access real component of null}} \ - // expected-note {{read of dereferenced null pointer}} + // both-note {{dereferencing a null pointer}} constexpr float pi = __imag *p; // both-error {{constant expr}} \ - // ref-note {{cannot access imaginary component of null}} + // both-note {{dereferencing a null pointer}} constexpr const _Complex double *q = &test3 + 1; constexpr double qr = __real *q; // ref-error {{constant expr}} \ // ref-note {{cannot access real component of pointer past the end}} diff --git a/clang/test/AST/ByteCode/const-eval.c b/clang/test/AST/ByteCode/const-eval.c index eab14c08ec809..3e228226ac8c1 100644 --- a/clang/test/AST/ByteCode/const-eval.c +++ b/clang/test/AST/ByteCode/const-eval.c @@ -180,6 +180,9 @@ typedef __INTPTR_TYPE__ intptr_t; const intptr_t A = (intptr_t)(((int*) 0) + 1); const intptr_t B = (intptr_t)(((char*)0) + 3); _Static_assert(A > B, ""); +int * GH149500_p = &(*(int *)0x400); +static const void *GH149500_q = &(*(const struct sysrq_key_op *)0); + #else #error :( #endif diff --git a/clang/test/AST/ByteCode/cxx11.cpp b/clang/test/AST/ByteCode/cxx11.cpp index b34e7823220e2..378702f9b3620 100644 --- a/clang/test/AST/ByteCode/cxx11.cpp +++ b/clang/test/AST/ByteCode/cxx11.cpp @@ -39,7 +39,8 @@ struct S { constexpr S s = { 5 }; constexpr const int *p = &s.m + 1; -constexpr const int *np2 = &(*(int(*)[4])nullptr)[0]; // ok +constexpr const int *np2 = &(*(int(*)[4])nullptr)[0]; // both-error {{constexpr variable 'np2' must be initialized by a constant expression}} \ + // both-note {{dereferencing a null pointer is not allowed in a constant expression}} constexpr int preDec(int x) { // both-error {{never produces a constant expression}} return --x; // both-note {{subexpression}} diff --git a/clang/test/AST/ByteCode/mutable.cpp b/clang/test/AST/ByteCode/mutable.cpp index aebbea920578c..35c5a0389921e 100644 --- a/clang/test/AST/ByteCode/mutable.cpp +++ b/clang/test/AST/ByteCode/mutable.cpp @@ -1,11 +1,7 @@ -// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++11 -verify=expected,expected11,both,both11 %s -// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++14 -verify=expected,expected14,both %s -// RUN: %clang_cc1 -std=c++11 -verify=ref,ref11,both,both11 %s -// RUN: %clang_cc1 -std=c++14 -verify=ref,ref14,both %s - - - - +// RUN: %clang_cc1 -std=c++11 -verify=expected,expected11,both,both11 %s -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++14 -verify=expected,expected14,both %s -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++11 -verify=ref,ref11,both,both11 %s +// RUN: %clang_cc1 -std=c++14 -verify=ref,ref14,both %s namespace Simple { struct S { @@ -26,3 +22,47 @@ namespace Simple { static_assert(s2.a2 == 12, ""); // both11-error {{not an integral constant expression}} \ // both11-note {{initializer of 's2' is not a constant expression}} } +#if __cplusplus >= 201402L +namespace ConstInMutable { + class B { + public: + + const int f; + constexpr B() : f(12) {} + }; + class A { + public: + mutable B b; + constexpr A() = default; + }; + constexpr int constInMutable() { + A a; + + int *m = (int*)&a.b.f; + *m = 12; // both-note {{modification of object of const-qualified type 'const int' is not allowed in a constant expression}} + return 1; + } + static_assert(constInMutable() == 1, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} +} + +namespace MutableInConst { + class C { + public: + mutable int c; + constexpr C() : c(50) {} + }; + class D { + public: + C c; + constexpr D() {} + }; + constexpr int mutableInConst() { + const D d{}; + int *m = (int*)&d.c.c; + *m = 12; + return 1; + } + static_assert(mutableInConst() == 1, ""); +} +#endif diff --git a/clang/test/AST/ByteCode/placement-new.cpp b/clang/test/AST/ByteCode/placement-new.cpp index 670def2d5870e..b587cd6eaf89c 100644 --- a/clang/test/AST/ByteCode/placement-new.cpp +++ b/clang/test/AST/ByteCode/placement-new.cpp @@ -486,3 +486,11 @@ namespace bitcast { } static_assert(foo() == 0); } + +constexpr int modify_const_variable() { + const int a = 10; + new ((int *)&a) int(12); // both-note {{modification of object of const-qualified type 'const int' is not allowed in a constant expression}} + return a; +} +static_assert(modify_const_variable()); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} diff --git a/clang/test/AST/ByteCode/records.cpp b/clang/test/AST/ByteCode/records.cpp index d369c64bc3904..5ca3e2d12e2df 100644 --- a/clang/test/AST/ByteCode/records.cpp +++ b/clang/test/AST/ByteCode/records.cpp @@ -413,7 +413,7 @@ namespace DeriveFailures { constexpr Derived(int i) : OtherVal(i) {} // ref-error {{never produces a constant expression}} \ // both-note {{non-constexpr constructor 'Base' cannot be used in a constant expression}} \ - // ref-note {{non-constexpr constructor 'Base' cannot be used in a constant expression}} + // ref-note {{non-constexpr constructor 'Base' cannot be used in a constant expression}} }; constexpr Derived D(12); // both-error {{must be initialized by a constant expression}} \ @@ -1660,9 +1660,9 @@ namespace NullptrCast { constexpr A *na = nullptr; constexpr B *nb = nullptr; constexpr A &ra = *nb; // both-error {{constant expression}} \ - // both-note {{cannot access base class of null pointer}} + // both-note {{dereferencing a null pointer}} constexpr B &rb = (B&)*na; // both-error {{constant expression}} \ - // both-note {{cannot access derived class of null pointer}} + // both-note {{dereferencing a null pointer}} constexpr bool test() { auto a = (A*)(B*)nullptr; @@ -1740,7 +1740,7 @@ namespace CtorOfInvalidClass { #if __cplusplus >= 202002L template concept ReferenceOf = Q; - /// This calls a valid and constexpr copy constructor of InvalidCtor, + /// This calls a valid and constexpr copy constructor of InvalidCtor, /// but should still be rejected. template auto R, typename Rep> int F; // both-error {{non-type template argument is not a constant expression}} #endif diff --git a/clang/test/AST/ByteCode/unions.cpp b/clang/test/AST/ByteCode/unions.cpp index 0fa44a259a4ff..7cfd0d677a7b3 100644 --- a/clang/test/AST/ByteCode/unions.cpp +++ b/clang/test/AST/ByteCode/unions.cpp @@ -847,6 +847,20 @@ namespace Activation2 { } static_assert(change_member_indirectly() == 4); } + +namespace CopyCtorMutable { + struct E { + union { // expected-note {{read of mutable member 'b'}} + int a; + mutable int b; // both-note {{here}} + }; + }; + constexpr E e1 = {{1}}; + constexpr E e2 = e1; // both-error {{constant}} \ + // ref-note {{read of mutable member 'b'}} \ + // both-note {{in call}} +} + #endif namespace AddressComparison { diff --git a/clang/test/AST/HLSL/is_structured_resource_element_compatible_concept.hlsl b/clang/test/AST/HLSL/is_structured_resource_element_compatible_concept.hlsl index a4f6e6c44794e..fa8d78f38494a 100644 --- a/clang/test/AST/HLSL/is_structured_resource_element_compatible_concept.hlsl +++ b/clang/test/AST/HLSL/is_structured_resource_element_compatible_concept.hlsl @@ -9,7 +9,7 @@ // CHECK: | `-TemplateTypeParm {{.*}} 'element_type' // CHECK: `-BinaryOperator {{.*}} 'bool' lvalue '>=' // CHECK: |-UnaryExprOrTypeTraitExpr {{.*}} 'bool' sizeof 'element_type' -// CHECK: `-IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK: `-IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 StructuredBuffer Buffer; diff --git a/clang/test/AST/ast-dump-APValue-lvalue.cpp b/clang/test/AST/ast-dump-APValue-lvalue.cpp index 51d22a5ba8b6d..f4cf2f5291760 100644 --- a/clang/test/AST/ast-dump-APValue-lvalue.cpp +++ b/clang/test/AST/ast-dump-APValue-lvalue.cpp @@ -67,6 +67,10 @@ void Test(int (&arr)[10]) { // CHECK-NEXT: | |-value: LValue Base=TypeInfoLValue typeid(int), Null=0, Offset=0, HasPath=1, PathLength=0, Path=() constexpr int(MP::*pmi) = (int MP::*)&P::x; - // CHECK: `-VarDecl {{.*}} col:{{.*}} pmi 'int (MP::*const)' constexpr cinit - // CHECK-NEXT: |-value: MemberPointer MP::x + // CHECK: | `-VarDecl {{.*}} col:{{.*}} pmi 'int (MP::*const)' constexpr cinit + // CHECK-NEXT: | |-value: MemberPointer MP::x + + constexpr int(MP::*pmn) = (int MP::*)nullptr; + // CHECK: `-VarDecl {{.*}} col:{{.*}} pmn 'int (MP::*const)' constexpr cinit + // CHECK-NEXT: |-value: MemberPointer null } diff --git a/clang/test/AST/ast-dump-array.cpp b/clang/test/AST/ast-dump-array.cpp index 15771f227df8a..5a982d34683ff 100644 --- a/clang/test/AST/ast-dump-array.cpp +++ b/clang/test/AST/ast-dump-array.cpp @@ -14,7 +14,7 @@ void testArrayInitExpr() auto l = [a]{ }; // CHECK: |-ArrayInitLoopExpr 0x{{[^ ]*}} 'int[10]' - // CHECK: | `-ArrayInitIndexExpr 0x{{[^ ]*}} <> 'unsigned long' + // CHECK: | `-ArrayInitIndexExpr 0x{{[^ ]*}} <> '__size_t':'unsigned long' } template diff --git a/clang/test/AST/ast-dump-expr-json.c b/clang/test/AST/ast-dump-expr-json.c index e910864eeed65..ecb6191c52200 100644 --- a/clang/test/AST/ast-dump-expr-json.c +++ b/clang/test/AST/ast-dump-expr-json.c @@ -3911,7 +3911,8 @@ void PrimaryExpressions(int a) { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "desugaredQualType": "unsigned long", +// CHECK-NEXT: "qualType": "__size_t" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "name": "sizeof", @@ -3964,7 +3965,8 @@ void PrimaryExpressions(int a) { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "desugaredQualType": "unsigned long", +// CHECK-NEXT: "qualType": "__size_t" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "name": "sizeof", @@ -3989,7 +3991,8 @@ void PrimaryExpressions(int a) { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "desugaredQualType": "unsigned long", +// CHECK-NEXT: "qualType": "__size_t" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "name": "alignof", diff --git a/clang/test/AST/ast-dump-expr-json.cpp b/clang/test/AST/ast-dump-expr-json.cpp index 5a762acad7917..11026c9d302f0 100644 --- a/clang/test/AST/ast-dump-expr-json.cpp +++ b/clang/test/AST/ast-dump-expr-json.cpp @@ -1545,7 +1545,8 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "desugaredQualType": "unsigned long", +// CHECK-NEXT: "qualType": "__size_t" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "name": "Ts" @@ -1587,7 +1588,8 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "long" +// CHECK-NEXT: "desugaredQualType": "long", +// CHECK-NEXT: "qualType": "__ptrdiff_t" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "opcode": "-", @@ -1726,7 +1728,7 @@ void TestNonADLCall3() { // CHECK-NEXT: "kind": "FunctionDecl", // CHECK-NEXT: "name": "operator new", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void *(unsigned long)" +// CHECK-NEXT: "qualType": "void *(__size_t)" // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: }, @@ -1755,7 +1757,7 @@ void TestNonADLCall3() { // CHECK-NEXT: "kind": "FunctionDecl", // CHECK-NEXT: "name": "operator new", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void *(unsigned long)" +// CHECK-NEXT: "qualType": "void *(__size_t)" // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: }, @@ -1785,7 +1787,7 @@ void TestNonADLCall3() { // CHECK-NEXT: "kind": "FunctionDecl", // CHECK-NEXT: "name": "operator new", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void *(unsigned long)" +// CHECK-NEXT: "qualType": "void *(__size_t)" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ @@ -1860,7 +1862,7 @@ void TestNonADLCall3() { // CHECK-NEXT: "kind": "FunctionDecl", // CHECK-NEXT: "name": "operator new[]", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void *(unsigned long)" +// CHECK-NEXT: "qualType": "void *(__size_t)" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ @@ -1880,7 +1882,8 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "desugaredQualType": "unsigned long", +// CHECK-NEXT: "qualType": "__size_t" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "castKind": "IntegralCast", @@ -1937,7 +1940,7 @@ void TestNonADLCall3() { // CHECK-NEXT: "kind": "FunctionDecl", // CHECK-NEXT: "name": "operator new[]", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void *(unsigned long)" +// CHECK-NEXT: "qualType": "void *(__size_t)" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ @@ -1957,7 +1960,8 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "desugaredQualType": "unsigned long", +// CHECK-NEXT: "qualType": "__size_t" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "castKind": "IntegralCast", @@ -2333,7 +2337,7 @@ void TestNonADLCall3() { // CHECK-NEXT: "kind": "FunctionDecl", // CHECK-NEXT: "name": "operator delete", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void (void *, unsigned long) noexcept" +// CHECK-NEXT: "qualType": "void (void *, __size_t) noexcept" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ diff --git a/clang/test/AST/ast-dump-expr.c b/clang/test/AST/ast-dump-expr.c index 959d61ec9794b..e7aba39be8f68 100644 --- a/clang/test/AST/ast-dump-expr.c +++ b/clang/test/AST/ast-dump-expr.c @@ -222,15 +222,15 @@ void UnaryOperators(int a, int *b) { // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int' sizeof a; - // CHECK: UnaryExprOrTypeTraitExpr 0x{{[^ ]*}} 'unsigned long' sizeof + // CHECK: UnaryExprOrTypeTraitExpr 0x{{[^ ]*}} '__size_t':'unsigned long' sizeof // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'int' lvalue ParmVar 0x{{[^ ]*}} 'a' 'int' sizeof(int); - // CHECK: UnaryExprOrTypeTraitExpr 0x{{[^ ]*}} 'unsigned long' sizeof 'int' + // CHECK: UnaryExprOrTypeTraitExpr 0x{{[^ ]*}} '__size_t':'unsigned long' sizeof 'int' _Alignof(int); // FIXME: Uses C++ spelling for alignof in C mode. - // CHECK: UnaryExprOrTypeTraitExpr 0x{{[^ ]*}} 'unsigned long' alignof 'int' + // CHECK: UnaryExprOrTypeTraitExpr 0x{{[^ ]*}} '__size_t':'unsigned long' alignof 'int' } struct S { diff --git a/clang/test/AST/ast-dump-expr.cpp b/clang/test/AST/ast-dump-expr.cpp index 8ccb39f8f3165..6fd429d1500a4 100644 --- a/clang/test/AST/ast-dump-expr.cpp +++ b/clang/test/AST/ast-dump-expr.cpp @@ -115,34 +115,34 @@ void Casting(const S *s) { template void UnaryExpressions(int *p) { sizeof...(Ts); - // CHECK: SizeOfPackExpr 0x{{[^ ]*}} 'unsigned long' 0x{{[^ ]*}} Ts + // CHECK: SizeOfPackExpr 0x{{[^ ]*}} '__size_t':'unsigned long' 0x{{[^ ]*}} Ts noexcept(p - p); // CHECK: CXXNoexceptExpr 0x{{[^ ]*}} 'bool' - // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} 'long' '-' + // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} '__ptrdiff_t':'long' '-' // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *' // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *' ::new int; - // CHECK: CXXNewExpr 0x{{[^ ]*}} 'int *' global Function 0x{{[^ ]*}} 'operator new' 'void *(unsigned long)' + // CHECK: CXXNewExpr 0x{{[^ ]*}} 'int *' global Function 0x{{[^ ]*}} 'operator new' 'void *(__size_t)' new (int); - // CHECK: CXXNewExpr 0x{{[^ ]*}} 'int *' Function 0x{{[^ ]*}} 'operator new' 'void *(unsigned long)' + // CHECK: CXXNewExpr 0x{{[^ ]*}} 'int *' Function 0x{{[^ ]*}} 'operator new' 'void *(__size_t)' new int{12}; - // CHECK: CXXNewExpr 0x{{[^ ]*}} 'int *' Function 0x{{[^ ]*}} 'operator new' 'void *(unsigned long)' + // CHECK: CXXNewExpr 0x{{[^ ]*}} 'int *' Function 0x{{[^ ]*}} 'operator new' 'void *(__size_t)' // CHECK-NEXT: InitListExpr 0x{{[^ ]*}} 'int' // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} 'int' 12 new int[2]; - // CHECK: CXXNewExpr 0x{{[^ ]*}} 'int *' array Function 0x{{[^ ]*}} 'operator new[]' 'void *(unsigned long)' + // CHECK: CXXNewExpr 0x{{[^ ]*}} 'int *' array Function 0x{{[^ ]*}} 'operator new[]' 'void *(__size_t)' // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} 'int' 2 new int[2]{1, 2}; - // CHECK: CXXNewExpr 0x{{[^ ]*}} 'int *' array Function 0x{{[^ ]*}} 'operator new[]' 'void *(unsigned long)' + // CHECK: CXXNewExpr 0x{{[^ ]*}} 'int *' array Function 0x{{[^ ]*}} 'operator new[]' 'void *(__size_t)' // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} 'int' 2 // CHECK-NEXT: InitListExpr 0x{{[^ ]*}} 'int[2]' @@ -164,7 +164,7 @@ void UnaryExpressions(int *p) { // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *' ::delete p; - // CHECK: CXXDeleteExpr 0x{{[^ ]*}} 'void' global Function 0x{{[^ ]*}} 'operator delete' 'void (void *, unsigned long) noexcept' + // CHECK: CXXDeleteExpr 0x{{[^ ]*}} 'void' global Function 0x{{[^ ]*}} 'operator delete' 'void (void *, __size_t) noexcept' // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *' diff --git a/clang/test/AST/ast-dump-openmp-distribute-parallel-for-simd.c b/clang/test/AST/ast-dump-openmp-distribute-parallel-for-simd.c index 10f27e759b5b1..672607fa90670 100644 --- a/clang/test/AST/ast-dump-openmp-distribute-parallel-for-simd.c +++ b/clang/test/AST/ast-dump-openmp-distribute-parallel-for-simd.c @@ -57,8 +57,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | `-NullStmt {{.*}} // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-distribute-parallel-for-simd.c:4:1) *const restrict' // CHECK-NEXT: | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | `-IntegerLiteral {{.*}} 'int' 0 @@ -97,8 +97,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | `-NullStmt {{.*}} // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-distribute-parallel-for-simd.c:10:1) *const restrict' // CHECK-NEXT: | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -144,8 +144,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | `-NullStmt {{.*}} // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-distribute-parallel-for-simd.c:17:1) *const restrict' // CHECK-NEXT: | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -191,8 +191,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | `-NullStmt {{.*}} // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-distribute-parallel-for-simd.c:24:1) *const restrict' // CHECK-NEXT: | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -251,8 +251,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | `-NullStmt {{.*}} // CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-distribute-parallel-for-simd.c:31:1) *const restrict' // CHECK-NEXT: | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | `-IntegerLiteral {{.*}} 'int' 0 diff --git a/clang/test/AST/ast-dump-openmp-distribute-parallel-for.c b/clang/test/AST/ast-dump-openmp-distribute-parallel-for.c index 419ba57191039..8eedf8ac8bc58 100644 --- a/clang/test/AST/ast-dump-openmp-distribute-parallel-for.c +++ b/clang/test/AST/ast-dump-openmp-distribute-parallel-for.c @@ -57,8 +57,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | `-NullStmt {{.*}} // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-distribute-parallel-for.c:4:1) *const restrict' // CHECK-NEXT: | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | `-IntegerLiteral {{.*}} 'int' 0 @@ -97,8 +97,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | `-NullStmt {{.*}} // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-distribute-parallel-for.c:10:1) *const restrict' // CHECK-NEXT: | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -144,8 +144,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | `-NullStmt {{.*}} // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-distribute-parallel-for.c:17:1) *const restrict' // CHECK-NEXT: | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -191,8 +191,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | `-NullStmt {{.*}} // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-distribute-parallel-for.c:24:1) *const restrict' // CHECK-NEXT: | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -251,8 +251,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | `-NullStmt {{.*}} // CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-distribute-parallel-for.c:31:1) *const restrict' // CHECK-NEXT: | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | `-IntegerLiteral {{.*}} 'int' 0 diff --git a/clang/test/AST/ast-dump-openmp-target-teams-distribute-parallel-for-simd.c b/clang/test/AST/ast-dump-openmp-target-teams-distribute-parallel-for-simd.c index c209a0456d7a0..64e19ce0a53bf 100644 --- a/clang/test/AST/ast-dump-openmp-target-teams-distribute-parallel-for-simd.c +++ b/clang/test/AST/ast-dump-openmp-target-teams-distribute-parallel-for-simd.c @@ -65,8 +65,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:4:1) *const restrict' // CHECK-NEXT: | | | | | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -94,8 +94,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:4:1) *const restrict' // CHECK-NEXT: | | | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -123,8 +123,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:4:1) *const restrict' // CHECK-NEXT: | | | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -152,8 +152,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:4:1) *const restrict' // CHECK-NEXT: | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -189,8 +189,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:4:1) *const restrict' // CHECK-NEXT: | | | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -218,8 +218,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:4:1) *const restrict' // CHECK-NEXT: | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -247,8 +247,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:4:1) *const restrict' // CHECK-NEXT: | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -276,8 +276,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | `-NullStmt {{.*}} // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:4:1) *const restrict' // CHECK-NEXT: | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | `-IntegerLiteral {{.*}} 'int' 0 @@ -325,8 +325,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:10:1) *const restrict' // CHECK-NEXT: | | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -371,8 +371,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:10:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -417,8 +417,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:10:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -463,8 +463,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:10:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -517,8 +517,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:10:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -563,8 +563,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:10:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -609,8 +609,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:10:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -655,8 +655,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | `-NullStmt {{.*}} // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:10:1) *const restrict' // CHECK-NEXT: | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -711,8 +711,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:17:1) *const restrict' // CHECK-NEXT: | | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -757,8 +757,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:17:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -803,8 +803,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:17:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -849,8 +849,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:17:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -903,8 +903,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:17:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -949,8 +949,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:17:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -995,8 +995,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:17:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1041,8 +1041,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | `-NullStmt {{.*}} // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:17:1) *const restrict' // CHECK-NEXT: | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1097,8 +1097,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:24:1) *const restrict' // CHECK-NEXT: | | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1143,8 +1143,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:24:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1189,8 +1189,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:24:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1235,8 +1235,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:24:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1289,8 +1289,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:24:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1335,8 +1335,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:24:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1381,8 +1381,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:24:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1427,8 +1427,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | `-NullStmt {{.*}} // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:24:1) *const restrict' // CHECK-NEXT: | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1497,8 +1497,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:31:1) *const restrict' // CHECK-NEXT: | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1560,8 +1560,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:31:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1623,8 +1623,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:31:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1686,8 +1686,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:31:1) *const restrict' // CHECK-NEXT: | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1757,8 +1757,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:31:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1820,8 +1820,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:31:1) *const restrict' // CHECK-NEXT: | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1883,8 +1883,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:31:1) *const restrict' // CHECK-NEXT: | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1946,8 +1946,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | `-NullStmt {{.*}} // CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for-simd.c:31:1) *const restrict' // CHECK-NEXT: | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | `-IntegerLiteral {{.*}} 'int' 0 diff --git a/clang/test/AST/ast-dump-openmp-target-teams-distribute-parallel-for.c b/clang/test/AST/ast-dump-openmp-target-teams-distribute-parallel-for.c index b13e096101e63..cf3f4bfcaf225 100644 --- a/clang/test/AST/ast-dump-openmp-target-teams-distribute-parallel-for.c +++ b/clang/test/AST/ast-dump-openmp-target-teams-distribute-parallel-for.c @@ -65,8 +65,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:4:1) *const restrict' // CHECK-NEXT: | | | | | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -94,8 +94,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:4:1) *const restrict' // CHECK-NEXT: | | | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -123,8 +123,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:4:1) *const restrict' // CHECK-NEXT: | | | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -152,8 +152,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:4:1) *const restrict' // CHECK-NEXT: | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -189,8 +189,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:4:1) *const restrict' // CHECK-NEXT: | | | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -218,8 +218,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:4:1) *const restrict' // CHECK-NEXT: | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -247,8 +247,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:4:1) *const restrict' // CHECK-NEXT: | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -276,8 +276,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | `-NullStmt {{.*}} // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:4:1) *const restrict' // CHECK-NEXT: | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | `-IntegerLiteral {{.*}} 'int' 0 @@ -325,8 +325,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:10:1) *const restrict' // CHECK-NEXT: | | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -371,8 +371,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:10:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -417,8 +417,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:10:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -463,8 +463,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:10:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -517,8 +517,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:10:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -563,8 +563,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:10:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -609,8 +609,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:10:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -655,8 +655,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | `-NullStmt {{.*}} // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:10:1) *const restrict' // CHECK-NEXT: | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -711,8 +711,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:17:1) *const restrict' // CHECK-NEXT: | | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -757,8 +757,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:17:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -803,8 +803,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:17:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -849,8 +849,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:17:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -903,8 +903,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:17:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -949,8 +949,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:17:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -995,8 +995,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:17:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1041,8 +1041,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | `-NullStmt {{.*}} // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:17:1) *const restrict' // CHECK-NEXT: | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1097,8 +1097,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:24:1) *const restrict' // CHECK-NEXT: | | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1143,8 +1143,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:24:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1189,8 +1189,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:24:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1235,8 +1235,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:24:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1289,8 +1289,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:24:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1335,8 +1335,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:24:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1381,8 +1381,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:24:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1427,8 +1427,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | `-NullStmt {{.*}} // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:24:1) *const restrict' // CHECK-NEXT: | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1497,8 +1497,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:31:1) *const restrict' // CHECK-NEXT: | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1560,8 +1560,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:31:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1623,8 +1623,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:31:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1686,8 +1686,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:31:1) *const restrict' // CHECK-NEXT: | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1757,8 +1757,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:31:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1820,8 +1820,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:31:1) *const restrict' // CHECK-NEXT: | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1883,8 +1883,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:31:1) *const restrict' // CHECK-NEXT: | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1946,8 +1946,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | `-NullStmt {{.*}} // CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-target-teams-distribute-parallel-for.c:31:1) *const restrict' // CHECK-NEXT: | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | `-IntegerLiteral {{.*}} 'int' 0 diff --git a/clang/test/AST/ast-dump-openmp-teams-distribute-parallel-for-simd.c b/clang/test/AST/ast-dump-openmp-teams-distribute-parallel-for-simd.c index 14356882b599a..c8da8cd1a5efa 100644 --- a/clang/test/AST/ast-dump-openmp-teams-distribute-parallel-for-simd.c +++ b/clang/test/AST/ast-dump-openmp-teams-distribute-parallel-for-simd.c @@ -71,8 +71,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:5:1) *const restrict' // CHECK-NEXT: | | | | | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -99,8 +99,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:5:1) *const restrict' // CHECK-NEXT: | | | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -127,8 +127,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:5:1) *const restrict' // CHECK-NEXT: | | | | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -155,8 +155,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:5:1) *const restrict' // CHECK-NEXT: | | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -211,8 +211,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:5:1) *const restrict' // CHECK-NEXT: | | | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -239,8 +239,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:5:1) *const restrict' // CHECK-NEXT: | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -267,8 +267,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:5:1) *const restrict' // CHECK-NEXT: | | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -295,8 +295,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:5:1) *const restrict' // CHECK-NEXT: | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -363,8 +363,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:12:1) *const restrict' // CHECK-NEXT: | | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -407,8 +407,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:12:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -451,8 +451,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:12:1) *const restrict' // CHECK-NEXT: | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -495,8 +495,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:12:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -568,8 +568,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:12:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -612,8 +612,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:12:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -656,8 +656,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:12:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -700,8 +700,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:12:1) *const restrict' // CHECK-NEXT: | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -775,8 +775,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:20:1) *const restrict' // CHECK-NEXT: | | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -819,8 +819,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:20:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -863,8 +863,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:20:1) *const restrict' // CHECK-NEXT: | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -907,8 +907,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:20:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -984,8 +984,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:20:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1028,8 +1028,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:20:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1072,8 +1072,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:20:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1116,8 +1116,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:20:1) *const restrict' // CHECK-NEXT: | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1191,8 +1191,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:28:1) *const restrict' // CHECK-NEXT: | | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1235,8 +1235,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:28:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1279,8 +1279,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:28:1) *const restrict' // CHECK-NEXT: | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1323,8 +1323,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:28:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1419,8 +1419,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:28:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1463,8 +1463,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:28:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1507,8 +1507,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:28:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1551,8 +1551,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:28:1) *const restrict' // CHECK-NEXT: | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1659,8 +1659,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:36:1) *const restrict' // CHECK-NEXT: | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1719,8 +1719,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:36:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1779,8 +1779,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:36:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1839,8 +1839,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:36:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1952,8 +1952,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:36:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -2012,8 +2012,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:36:1) *const restrict' // CHECK-NEXT: | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -2072,8 +2072,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:36:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -2132,8 +2132,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | `-NullStmt {{.*}} // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for-simd.c:36:1) *const restrict' // CHECK-NEXT: | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | `-IntegerLiteral {{.*}} 'int' 0 diff --git a/clang/test/AST/ast-dump-openmp-teams-distribute-parallel-for.c b/clang/test/AST/ast-dump-openmp-teams-distribute-parallel-for.c index 0f983cfdff1dc..09b649cbb3660 100644 --- a/clang/test/AST/ast-dump-openmp-teams-distribute-parallel-for.c +++ b/clang/test/AST/ast-dump-openmp-teams-distribute-parallel-for.c @@ -71,8 +71,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:5:1) *const restrict' // CHECK-NEXT: | | | | | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -99,8 +99,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:5:1) *const restrict' // CHECK-NEXT: | | | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -127,8 +127,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:5:1) *const restrict' // CHECK-NEXT: | | | | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -155,8 +155,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:5:1) *const restrict' // CHECK-NEXT: | | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -211,8 +211,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:5:1) *const restrict' // CHECK-NEXT: | | | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -239,8 +239,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:5:1) *const restrict' // CHECK-NEXT: | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -267,8 +267,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:5:1) *const restrict' // CHECK-NEXT: | | | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -295,8 +295,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:5:1) *const restrict' // CHECK-NEXT: | | | `-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -363,8 +363,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:12:1) *const restrict' // CHECK-NEXT: | | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -407,8 +407,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:12:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -451,8 +451,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:12:1) *const restrict' // CHECK-NEXT: | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -495,8 +495,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:12:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -568,8 +568,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:12:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -612,8 +612,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:12:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -656,8 +656,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:12:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -700,8 +700,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:12:1) *const restrict' // CHECK-NEXT: | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -775,8 +775,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:20:1) *const restrict' // CHECK-NEXT: | | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -819,8 +819,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:20:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -863,8 +863,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:20:1) *const restrict' // CHECK-NEXT: | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -907,8 +907,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:20:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -984,8 +984,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:20:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1028,8 +1028,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:20:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1072,8 +1072,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:20:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1116,8 +1116,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:20:1) *const restrict' // CHECK-NEXT: | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1191,8 +1191,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:28:1) *const restrict' // CHECK-NEXT: | | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1235,8 +1235,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:28:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1279,8 +1279,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:28:1) *const restrict' // CHECK-NEXT: | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1323,8 +1323,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:28:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1419,8 +1419,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:28:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1463,8 +1463,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:28:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1507,8 +1507,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:28:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1551,8 +1551,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:28:1) *const restrict' // CHECK-NEXT: | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1659,8 +1659,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:36:1) *const restrict' // CHECK-NEXT: | | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1719,8 +1719,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:36:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1779,8 +1779,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:36:1) *const restrict' // CHECK-NEXT: | | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1839,8 +1839,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:36:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -1952,8 +1952,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:36:1) *const restrict' // CHECK-NEXT: | | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -2012,8 +2012,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:36:1) *const restrict' // CHECK-NEXT: | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -2072,8 +2072,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | | | `-NullStmt {{.*}} // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:36:1) *const restrict' // CHECK-NEXT: | | | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | | | `-IntegerLiteral {{.*}} 'int' 0 @@ -2132,8 +2132,8 @@ void test_five(int x, int y, int z) { // CHECK-NEXT: | | | `-NullStmt {{.*}} // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int *const restrict' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit .bound_tid. 'const int *const restrict' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const unsigned long' -// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.lb. 'const __size_t':'const unsigned long' +// CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit used .previous.ub. 'const __size_t':'const unsigned long' // CHECK-NEXT: | | |-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (unnamed at {{.*}}ast-dump-openmp-teams-distribute-parallel-for.c:36:1) *const restrict' // CHECK-NEXT: | | |-VarDecl {{.*}} col:12 used i 'int' cinit // CHECK-NEXT: | | | `-IntegerLiteral {{.*}} 'int' 0 diff --git a/clang/test/AST/ast-dump-stmt-json.cpp b/clang/test/AST/ast-dump-stmt-json.cpp index a473d17da9424..a8f113ce6a3d4 100644 --- a/clang/test/AST/ast-dump-stmt-json.cpp +++ b/clang/test/AST/ast-dump-stmt-json.cpp @@ -963,7 +963,7 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: "kind": "FunctionDecl", // CHECK-NEXT: "name": "operator new", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void *(unsigned long)" +// CHECK-NEXT: "qualType": "void *(__size_t)" // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: } @@ -994,7 +994,7 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: "kind": "FunctionDecl", // CHECK-NEXT: "name": "operator delete", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void (void *, unsigned long) noexcept" +// CHECK-NEXT: "qualType": "void (void *, __size_t) noexcept" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ @@ -1126,7 +1126,7 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: "kind": "FunctionDecl", // CHECK-NEXT: "name": "operator new[]", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void *(unsigned long)" +// CHECK-NEXT: "qualType": "void *(__size_t)" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ @@ -1146,7 +1146,8 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "desugaredQualType": "unsigned long", +// CHECK-NEXT: "qualType": "__size_t" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "castKind": "IntegralCast", @@ -1337,7 +1338,7 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: "kind": "FunctionDecl", // CHECK-NEXT: "name": "operator new", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void *(unsigned long)" +// CHECK-NEXT: "qualType": "void *(__size_t)" // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: } @@ -1369,7 +1370,7 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: "kind": "FunctionDecl", // CHECK-NEXT: "name": "operator delete", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void (void *, unsigned long) noexcept" +// CHECK-NEXT: "qualType": "void (void *, __size_t) noexcept" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ @@ -1444,7 +1445,7 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: "name": "operator new", // CHECK-NEXT: "mangledName": "_Znwm", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void *(unsigned long)" +// CHECK-NEXT: "qualType": "void *(__size_t)" // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ // CHECK-NEXT: { @@ -1457,7 +1458,8 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: }, // CHECK-NEXT: "isImplicit": true, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "desugaredQualType": "unsigned long", +// CHECK-NEXT: "qualType": "__size_t" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: { @@ -1503,7 +1505,7 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: "name": "operator new", // CHECK-NEXT: "mangledName": "_ZnwmSt11align_val_t", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void *(unsigned long, std::align_val_t)" +// CHECK-NEXT: "qualType": "void *(__size_t, std::align_val_t)" // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ // CHECK-NEXT: { @@ -1516,7 +1518,8 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: }, // CHECK-NEXT: "isImplicit": true, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "desugaredQualType": "unsigned long", +// CHECK-NEXT: "qualType": "__size_t" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: { @@ -1585,7 +1588,7 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: "name": "operator new[]", // CHECK-NEXT: "mangledName": "_Znam", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void *(unsigned long)" +// CHECK-NEXT: "qualType": "void *(__size_t)" // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ // CHECK-NEXT: { @@ -1598,7 +1601,8 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: }, // CHECK-NEXT: "isImplicit": true, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "desugaredQualType": "unsigned long", +// CHECK-NEXT: "qualType": "__size_t" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: { @@ -1644,7 +1648,7 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: "name": "operator new[]", // CHECK-NEXT: "mangledName": "_ZnamSt11align_val_t", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void *(unsigned long, std::align_val_t)" +// CHECK-NEXT: "qualType": "void *(__size_t, std::align_val_t)" // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ // CHECK-NEXT: { @@ -1657,7 +1661,8 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: }, // CHECK-NEXT: "isImplicit": true, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "desugaredQualType": "unsigned long", +// CHECK-NEXT: "qualType": "__size_t" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: { @@ -1821,7 +1826,7 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: "name": "operator delete", // CHECK-NEXT: "mangledName": "_ZdlPvm", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void (void *, unsigned long) noexcept" +// CHECK-NEXT: "qualType": "void (void *, __size_t) noexcept" // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ // CHECK-NEXT: { @@ -1847,7 +1852,8 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: }, // CHECK-NEXT: "isImplicit": true, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "desugaredQualType": "unsigned long", +// CHECK-NEXT: "qualType": "__size_t" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: { @@ -1874,7 +1880,7 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: "name": "operator delete", // CHECK-NEXT: "mangledName": "_ZdlPvmSt11align_val_t", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void (void *, unsigned long, std::align_val_t) noexcept" +// CHECK-NEXT: "qualType": "void (void *, __size_t, std::align_val_t) noexcept" // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ // CHECK-NEXT: { @@ -1900,7 +1906,8 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: }, // CHECK-NEXT: "isImplicit": true, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "desugaredQualType": "unsigned long", +// CHECK-NEXT: "qualType": "__size_t" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: { @@ -2036,7 +2043,7 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: "name": "operator delete[]", // CHECK-NEXT: "mangledName": "_ZdaPvm", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void (void *, unsigned long) noexcept" +// CHECK-NEXT: "qualType": "void (void *, __size_t) noexcept" // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ // CHECK-NEXT: { @@ -2062,7 +2069,8 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: }, // CHECK-NEXT: "isImplicit": true, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "desugaredQualType": "unsigned long", +// CHECK-NEXT: "qualType": "__size_t" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: { @@ -2089,7 +2097,7 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: "name": "operator delete[]", // CHECK-NEXT: "mangledName": "_ZdaPvmSt11align_val_t", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void (void *, unsigned long, std::align_val_t) noexcept" +// CHECK-NEXT: "qualType": "void (void *, __size_t, std::align_val_t) noexcept" // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ // CHECK-NEXT: { @@ -2115,7 +2123,8 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: }, // CHECK-NEXT: "isImplicit": true, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "desugaredQualType": "unsigned long", +// CHECK-NEXT: "qualType": "__size_t" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: { @@ -3881,7 +3890,8 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "desugaredQualType": "unsigned long", +// CHECK-NEXT: "qualType": "__size_t" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "name": "sizeof", @@ -3955,7 +3965,8 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "desugaredQualType": "unsigned long", +// CHECK-NEXT: "qualType": "__size_t" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "castKind": "IntegralCast", @@ -4085,7 +4096,8 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "desugaredQualType": "unsigned long", +// CHECK-NEXT: "qualType": "__size_t" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "name": "sizeof", @@ -4159,7 +4171,8 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "desugaredQualType": "unsigned long", +// CHECK-NEXT: "qualType": "__size_t" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "castKind": "IntegralCast", @@ -4980,7 +4993,8 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "long" +// CHECK-NEXT: "desugaredQualType": "long", +// CHECK-NEXT: "qualType": "__ptrdiff_t" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "value": "10" @@ -6503,7 +6517,8 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "long" +// CHECK-NEXT: "desugaredQualType": "long" +// CHECK-NEXT: "qualType": "__ptrdiff_t" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "value": "10" diff --git a/clang/test/AST/ast-dump-stmt.cpp b/clang/test/AST/ast-dump-stmt.cpp index 407584e5b82de..42c5f3b3498a4 100644 --- a/clang/test/AST/ast-dump-stmt.cpp +++ b/clang/test/AST/ast-dump-stmt.cpp @@ -206,7 +206,7 @@ void TestIteration() { // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} 'int *' '+' // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'int[10]' lvalue Var 0x{{[^ ]*}} '__range1' 'int (&)[10]' - // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} 'long' 10 + // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} '__ptrdiff_t':'long' 10 // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} 'bool' '!=' // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'int *' lvalue Var 0x{{[^ ]*}} '__begin1' 'int *' @@ -274,7 +274,7 @@ void TestIteration() { // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} 'int *' '+' // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'int[10]' lvalue Var 0x{{[^ ]*}} '__range1' 'int (&)[10]' - // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} 'long' 10 + // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} '__ptrdiff_t':'long' 10 // CHECK-NEXT: BinaryOperator 0x{{[^ ]*}} 'bool' '!=' // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'int *' lvalue Var 0x{{[^ ]*}} '__begin1' 'int *' diff --git a/clang/test/AST/ast-dump-traits.cpp b/clang/test/AST/ast-dump-traits.cpp index 3085e5883fd2e..72d2a2ae8603e 100644 --- a/clang/test/AST/ast-dump-traits.cpp +++ b/clang/test/AST/ast-dump-traits.cpp @@ -56,7 +56,7 @@ void test_unary_expr_or_type_trait() { // CHECK-NEXT: |-FunctionDecl {{.*}} line:20:6{{( imported)?}} test_array_type_trait 'void ()' // CHECK-NEXT: | `-CompoundStmt {{.*}} // CHECK-NEXT: | `-CStyleCastExpr {{.*}} 'void' -// CHECK-NEXT: | `-ArrayTypeTraitExpr {{.*}} 'unsigned long' __array_rank +// CHECK-NEXT: | `-ArrayTypeTraitExpr {{.*}} '__size_t':'unsigned long' __array_rank // CHECK-NEXT: |-FunctionDecl {{.*}} line:25:6{{( imported)?}} test_expression_trait 'void ()' // CHECK-NEXT: | `-CompoundStmt {{.*}} // CHECK-NEXT: | `-CStyleCastExpr {{.*}} 'void' @@ -64,8 +64,8 @@ void test_unary_expr_or_type_trait() { // CHECK-NEXT: `-FunctionDecl {{.*}} line:30:6{{( imported)?}} test_unary_expr_or_type_trait 'void ()' // CHECK-NEXT: `-CompoundStmt {{.*}} // CHECK-NEXT: |-CStyleCastExpr {{.*}} 'void' -// CHECK-NEXT: | `-UnaryExprOrTypeTraitExpr {{.*}} 'unsigned long' sizeof 'int' +// CHECK-NEXT: | `-UnaryExprOrTypeTraitExpr {{.*}} '__size_t':'unsigned long' sizeof 'int' // CHECK-NEXT: |-CStyleCastExpr {{.*}} 'void' -// CHECK-NEXT: | `-UnaryExprOrTypeTraitExpr {{.*}} 'unsigned long' alignof 'int' +// CHECK-NEXT: | `-UnaryExprOrTypeTraitExpr {{.*}} '__size_t':'unsigned long' alignof 'int' // CHECK-NEXT: `-CStyleCastExpr {{.*}} 'void' -// CHECK-NEXT: `-UnaryExprOrTypeTraitExpr {{.*}} 'unsigned long' __alignof 'int' +// CHECK-NEXT: `-UnaryExprOrTypeTraitExpr {{.*}} '__size_t':'unsigned long' __alignof 'int' diff --git a/clang/test/AST/ast-dump-types-errors-json.cpp b/clang/test/AST/ast-dump-types-errors-json.cpp index e15f8eeee20cc..d9f918f6c3d72 100644 --- a/clang/test/AST/ast-dump-types-errors-json.cpp +++ b/clang/test/AST/ast-dump-types-errors-json.cpp @@ -60,7 +60,8 @@ using TestContainsErrors = int[sizeof(undef())]; // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: "desugaredQualType": "unsigned long", +// CHECK-NEXT: "qualType": "__size_t" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", // CHECK-NEXT: "name": "sizeof", diff --git a/clang/test/Analysis/cfg.cpp b/clang/test/Analysis/cfg.cpp index 44a89df28e3b2..d6cef88dc18a6 100644 --- a/clang/test/Analysis/cfg.cpp +++ b/clang/test/Analysis/cfg.cpp @@ -70,7 +70,7 @@ void F(EmptyE e) { // CHECK-NEXT: Succs (1): B1 // CHECK: [B1] // CHECK-NEXT: 1: __builtin_object_size -// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, BuiltinFnToFnPtr, unsigned long (*)(const void *, int) noexcept) +// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, BuiltinFnToFnPtr, __size_t (*)(const void *, int) noexcept) // CHECK-NEXT: 3: [B1.2](dummy(), 0) // CHECK-NEXT: 4: (void)[B1.3] (CStyleCastExpr, ToVoid, void) // CHECK-NEXT: Preds (1): B2 diff --git a/clang/test/Analysis/div-zero-cxx20.cpp b/clang/test/Analysis/div-zero-cxx20.cpp new file mode 100644 index 0000000000000..00ea96e796777 --- /dev/null +++ b/clang/test/Analysis/div-zero-cxx20.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core.DivideZero -std=c++20 -verify %s + +namespace GH148875 { +struct A { + int x; + A(int v) : x(v) {} +}; + +struct B { + int x; + B() : x(0) {} +}; + +struct C { + int x, y; + C(int a, int b) : x(a), y(b) {} +}; + +struct D { + int x; +}; + +struct E { + D d; + E(int a) : d(a) {} +}; + +struct F { + int x; +}; + +int t1() { + A a{42}; + return 1 / (a.x - 42); // expected-warning {{Division by zero}} +} + +int t2() { + B b{}; + return 1 / b.x; // expected-warning {{Division by zero}} +} + +int t3() { + C c1{1, -1}; + return 1 / (c1.x + c1.y); // expected-warning {{Division by zero}} +} + +int t4() { + C c2{0, 0}; + return 1 / (c2.x + c2.y); // expected-warning {{Division by zero}} +} + +int t5() { + E e{32}; + return 1 / (e.d.x - 32); // expected-warning {{Division by zero}} +} + +int t6() { + F f(32); + return 1 / (f.x - 32); // expected-warning {{Division by zero}} +} +} // namespace GH148875 diff --git a/clang/test/Analysis/div-zero.cpp b/clang/test/Analysis/div-zero.cpp index 063450d8883b0..51ea25e828a18 100644 --- a/clang/test/Analysis/div-zero.cpp +++ b/clang/test/Analysis/div-zero.cpp @@ -11,3 +11,63 @@ int fooPR10616 (int qX ) { return (a % (qX-1)); // expected-warning {{Division by zero}} } + +namespace GH148875 { +struct A { + int x; + A(int v) : x(v) {} +}; + +struct B { + int x; + B() : x(0) {} +}; + +struct C { + int x, y; + C(int a, int b) : x(a), y(b) {} +}; + +struct D { + int x; +}; + +struct E { + D d; + E(int a) : d{a} {} +}; + +struct F { + int x; +}; + +int t1() { + A a{42}; + return 1 / (a.x - 42); // expected-warning {{Division by zero}} +} + +int t2() { + B b{}; + return 1 / b.x; // expected-warning {{Division by zero}} +} + +int t3() { + C c1{1, -1}; + return 1 / (c1.x + c1.y); // expected-warning {{Division by zero}} +} + +int t4() { + C c2{0, 0}; + return 1 / (c2.x + c2.y); // expected-warning {{Division by zero}} +} + +int t5() { + E e{32}; + return 1 / (e.d.x - 32); // expected-warning {{Division by zero}} +} + +int t6() { + F f{32}; + return 1 / (f.x - 32); // expected-warning {{Division by zero}} +} +} diff --git a/clang/test/Analysis/explain-svals.cpp b/clang/test/Analysis/explain-svals.cpp index 267980c3b20c8..dfc650223c9e7 100644 --- a/clang/test/Analysis/explain-svals.cpp +++ b/clang/test/Analysis/explain-svals.cpp @@ -46,7 +46,7 @@ void test_1(int param, void *ptr) { void test_2(char *ptr, int ext) { clang_analyzer_explain((void *) "asdf"); // expected-warning-re{{{{^pointer to element of type 'char' with index 0 of string literal "asdf"$}}}} - clang_analyzer_explain(strlen(ptr)); // expected-warning-re{{{{^metadata of type 'unsigned long' tied to pointee of argument 'ptr'$}}}} + clang_analyzer_explain(strlen(ptr)); // expected-warning-re{{{{^metadata of type '__size_t' tied to pointee of argument 'ptr'$}}}} clang_analyzer_explain(conjure()); // expected-warning-re{{{{^symbol of type 'int' conjured at CFG element 'conjure\(\)'$}}}} clang_analyzer_explain(glob); // expected-warning-re{{{{^value derived from \(symbol of type 'int' conjured at CFG element 'conjure\(\)'\) for global variable 'glob'$}}}} clang_analyzer_explain(glob_ptr); // expected-warning-re{{{{^value derived from \(symbol of type 'int' conjured at CFG element 'conjure\(\)'\) for global variable 'glob_ptr'$}}}} diff --git a/clang/test/Analysis/std-c-library-functions-arg-weakdeps.c b/clang/test/Analysis/std-c-library-functions-arg-weakdeps.c index 1f0d3627fae34..ba5bc57928b0c 100644 --- a/clang/test/Analysis/std-c-library-functions-arg-weakdeps.c +++ b/clang/test/Analysis/std-c-library-functions-arg-weakdeps.c @@ -20,7 +20,7 @@ // RUN: -triple x86_64-unknown-linux 2>&1 | FileCheck %s // CHECK: Loaded summary for: int isalnum(int) -// CHECK: Loaded summary for: unsigned long fread(void *restrict, size_t, size_t, FILE *restrict) __attribute__((nonnull(1))) +// CHECK: Loaded summary for: __size_t fread(void *restrict, size_t, size_t, FILE *restrict) __attribute__((nonnull(1))) // CHECK: Loaded summary for: int fileno(FILE *stream) void initializeSummaryMap(void); diff --git a/clang/test/Analysis/std-c-library-functions-lookup.c b/clang/test/Analysis/std-c-library-functions-lookup.c index e47d9bddda91b..8182e5a1f5fde 100644 --- a/clang/test/Analysis/std-c-library-functions-lookup.c +++ b/clang/test/Analysis/std-c-library-functions-lookup.c @@ -6,7 +6,7 @@ // RUN: -analyzer-config eagerly-assume=false \ // RUN: -triple i686-unknown-linux 2>&1 | FileCheck %s -// CHECK: Loaded summary for: unsigned int fread(void *restrict, size_t, size_t, FILE *restrict) +// CHECK: Loaded summary for: __size_t fread(void *restrict, size_t, size_t, FILE *restrict) typedef typeof(sizeof(int)) size_t; typedef struct FILE FILE; diff --git a/clang/test/Analysis/std-c-library-functions-vs-stream-checker.c b/clang/test/Analysis/std-c-library-functions-vs-stream-checker.c index b99cc30149c91..887817ba8551e 100644 --- a/clang/test/Analysis/std-c-library-functions-vs-stream-checker.c +++ b/clang/test/Analysis/std-c-library-functions-vs-stream-checker.c @@ -31,8 +31,8 @@ // Verify that the summaries are loaded when the StdLibraryFunctionsChecker is // enabled. // CHECK: Loaded summary for: int getchar(void) -// CHECK-NEXT: Loaded summary for: unsigned long fread(void *restrict, size_t, size_t, FILE *restrict) -// CHECK-NEXT: Loaded summary for: unsigned long fwrite(const void *restrict, size_t, size_t, FILE *restrict) +// CHECK-NEXT: Loaded summary for: __size_t fread(void *restrict, size_t, size_t, FILE *restrict) +// CHECK-NEXT: Loaded summary for: __size_t fwrite(const void *restrict, size_t, size_t, FILE *restrict) #include "Inputs/system-header-simulator.h" diff --git a/clang/test/Analysis/std-c-library-functions.c b/clang/test/Analysis/std-c-library-functions.c index b03a1a5656517..b5f663493a676 100644 --- a/clang/test/Analysis/std-c-library-functions.c +++ b/clang/test/Analysis/std-c-library-functions.c @@ -59,8 +59,8 @@ // CHECK-NEXT: Loaded summary for: int tolower(int) // CHECK-NEXT: Loaded summary for: int toascii(int) // CHECK-NEXT: Loaded summary for: int getchar(void) -// CHECK-NEXT: Loaded summary for: unsigned int fread(void *restrict, size_t, size_t, FILE *restrict) -// CHECK-NEXT: Loaded summary for: unsigned int fwrite(const void *restrict, size_t, size_t, FILE *restrict) +// CHECK-NEXT: Loaded summary for: __size_t fread(void *restrict, size_t, size_t, FILE *restrict) +// CHECK-NEXT: Loaded summary for: __size_t fwrite(const void *restrict, size_t, size_t, FILE *restrict) // CHECK-NEXT: Loaded summary for: ssize_t read(int, void *, size_t) // CHECK-NEXT: Loaded summary for: ssize_t write(int, const void *, size_t) // CHECK-NEXT: Loaded summary for: ssize_t getline(char **restrict, size_t *restrict, FILE *restrict) diff --git a/clang/test/C/C2y/n3353.c b/clang/test/C/C2y/n3353.c index cd61cbf039067..a2e08cf6344db 100644 --- a/clang/test/C/C2y/n3353.c +++ b/clang/test/C/C2y/n3353.c @@ -44,7 +44,12 @@ static const void *ptr = 0o0; /* ext-warning {{octal integer literals are a C2y #endif // 0 by itself is not deprecated, of course. -int k = 0; +int k1 = 0; +unsigned int k2 = 0u; +long k3 = 0l; +unsigned long k4 = 0ul; +long long k5 = 0ll; +unsigned long long k6 = 0ull; // Test a preprocessor use of 0 by itself, which is also not deprecated. #if 0 @@ -65,7 +70,6 @@ static_assert(__extension__ _Generic(typeof(l), const int : 1, default : 0)); // // Note that 0o by itself is an invalid literal. int m = 0o; /* expected-error {{invalid suffix 'o' on integer constant}} - c2y-warning {{octal literals without a '0o' prefix are deprecated}} */ // Ensure negation works as expected. @@ -83,13 +87,11 @@ int n = 0o18; /* expected-error {{invalid digit '8' in octal constant}} cpp-warning {{octal integer literals are a Clang extension}} */ int o1 = 0o8; /* expected-error {{invalid suffix 'o8' on integer constant}} - c2y-warning {{octal literals without a '0o' prefix are deprecated}} */ // FIXME: however, it matches the behavior for hex literals in terms of the // error reported. Unfortunately, we then go on to think 0 is an octal literal // without a prefix, which is again a bit confusing. int o2 = 0xG; /* expected-error {{invalid suffix 'xG' on integer constant}} - c2y-warning {{octal literals without a '0o' prefix are deprecated}} */ // Show that floating-point suffixes on octal literals are rejected. @@ -130,7 +132,6 @@ constexpr int p = 0o0'1'2'3'4'5'6'7; /* compat-warning {{octal integer literals */ static_assert(p == 01234567); // c2y-warning {{octal literals without a '0o' prefix are deprecated}} int q = 0o'0'1; /* expected-error {{invalid suffix 'o'0'1' on integer constant}} - c2y-warning {{octal literals without a '0o' prefix are deprecated}} */ #define M 0o123 diff --git a/clang/test/CIR/CodeGen/bitfields.c b/clang/test/CIR/CodeGen/bitfields.c index 896acbfc854a4..a73c076ea81ab 100644 --- a/clang/test/CIR/CodeGen/bitfields.c +++ b/clang/test/CIR/CodeGen/bitfields.c @@ -87,14 +87,14 @@ int load_field(S* s) { // CIR: [[TMP0:%.*]] = cir.alloca !cir.ptr, !cir.ptr>, ["s", init] // CIR: [[TMP1:%.*]] = cir.load{{.*}} [[TMP0]] : !cir.ptr>, !cir.ptr // CIR: [[TMP2:%.*]] = cir.get_member [[TMP1]][0] {name = "c"} : !cir.ptr -> !cir.ptr -// CIR: [[TMP3:%.*]] = cir.get_bitfield(#bfi_c, [[TMP2]] : !cir.ptr) -> !s32i +// CIR: [[TMP3:%.*]] = cir.get_bitfield align(4) (#bfi_c, [[TMP2]] : !cir.ptr) -> !s32i // LLVM: define dso_local i32 @load_field // LLVM: [[TMP0:%.*]] = alloca ptr, i64 1, align 8 // LLVM: [[TMP1:%.*]] = alloca i32, i64 1, align 4 // LLVM: [[TMP2:%.*]] = load ptr, ptr [[TMP0]], align 8 // LLVM: [[TMP3:%.*]] = getelementptr %struct.S, ptr [[TMP2]], i32 0, i32 0 -// LLVM: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8 +// LLVM: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 4 // LLVM: [[TMP5:%.*]] = shl i64 [[TMP4]], 15 // LLVM: [[TMP6:%.*]] = ashr i64 [[TMP5]], 47 // LLVM: [[TMP7:%.*]] = trunc i64 [[TMP6]] to i32 @@ -115,13 +115,13 @@ unsigned int load_field_unsigned(A* s) { //CIR: [[TMP0:%.*]] = cir.alloca !cir.ptr, !cir.ptr>, ["s", init] {alignment = 8 : i64} //CIR: [[TMP1:%.*]] = cir.load align(8) [[TMP0]] : !cir.ptr>, !cir.ptr //CIR: [[TMP2:%.*]] = cir.get_member [[TMP1]][3] {name = "more_bits"} : !cir.ptr -> !cir.ptr -//CIR: [[TMP3:%.*]] = cir.get_bitfield(#bfi_more_bits, [[TMP2]] : !cir.ptr) -> !u32i +//CIR: [[TMP3:%.*]] = cir.get_bitfield align(1) (#bfi_more_bits, [[TMP2]] : !cir.ptr) -> !u32i //LLVM: define dso_local i32 @load_field_unsigned //LLVM: [[TMP0:%.*]] = alloca ptr, i64 1, align 8 //LLVM: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8 //LLVM: [[TMP2:%.*]] = getelementptr %struct.A, ptr [[TMP1]], i32 0, i32 3 -//LLVM: [[TMP3:%.*]] = load i16, ptr [[TMP2]], align 2 +//LLVM: [[TMP3:%.*]] = load i16, ptr [[TMP2]], align 1 //LLVM: [[TMP4:%.*]] = lshr i16 [[TMP3]], 3 //LLVM: [[TMP5:%.*]] = and i16 [[TMP4]], 15 //LLVM: [[TMP6:%.*]] = zext i16 [[TMP5]] to i32 @@ -143,15 +143,15 @@ void store_field() { // CIR: [[TMP0:%.*]] = cir.alloca !rec_S, !cir.ptr // CIR: [[TMP1:%.*]] = cir.const #cir.int<3> : !s32i // CIR: [[TMP2:%.*]] = cir.get_member [[TMP0]][1] {name = "e"} : !cir.ptr -> !cir.ptr -// CIR: cir.set_bitfield(#bfi_e, [[TMP2]] : !cir.ptr, [[TMP1]] : !s32i) +// CIR: cir.set_bitfield align(4) (#bfi_e, [[TMP2]] : !cir.ptr, [[TMP1]] : !s32i) // LLVM: define dso_local void @store_field() // LLVM: [[TMP0:%.*]] = alloca %struct.S, i64 1, align 4 // LLVM: [[TMP1:%.*]] = getelementptr %struct.S, ptr [[TMP0]], i32 0, i32 1 -// LLVM: [[TMP2:%.*]] = load i16, ptr [[TMP1]], align 2 +// LLVM: [[TMP2:%.*]] = load i16, ptr [[TMP1]], align 4 // LLVM: [[TMP3:%.*]] = and i16 [[TMP2]], -32768 // LLVM: [[TMP4:%.*]] = or i16 [[TMP3]], 3 -// LLVM: store i16 [[TMP4]], ptr [[TMP1]], align 2 +// LLVM: store i16 [[TMP4]], ptr [[TMP1]], align 4 // OGCG: define dso_local void @store_field() // OGCG: [[TMP0:%.*]] = alloca %struct.S, align 4 @@ -169,24 +169,24 @@ void store_bitfield_to_bitfield() { // CIR: cir.func {{.*@store_bitfield_to_bitfield}} // CIR: [[TMP0:%.*]] = cir.alloca !rec_S, !cir.ptr, ["s"] {alignment = 4 : i64} // CIR: [[TMP1:%.*]] = cir.get_member [[TMP0]][0] {name = "c"} : !cir.ptr -> !cir.ptr -// CIR: [[TMP2:%.*]] = cir.get_bitfield(#bfi_c, [[TMP1]] : !cir.ptr) -> !s32i +// CIR: [[TMP2:%.*]] = cir.get_bitfield align(4) (#bfi_c, [[TMP1]] : !cir.ptr) -> !s32i // CIR: [[TMP3:%.*]] = cir.get_member [[TMP0]][0] {name = "a"} : !cir.ptr -> !cir.ptr -// CIR: [[TMP4:%.*]] = cir.set_bitfield(#bfi_a, [[TMP3]] : !cir.ptr, [[TMP2]] : !s32i) -> !s32i +// CIR: [[TMP4:%.*]] = cir.set_bitfield align(4) (#bfi_a, [[TMP3]] : !cir.ptr, [[TMP2]] : !s32i) -> !s32i // LLVM: define dso_local void @store_bitfield_to_bitfield() // LLVM: [[TMP0:%.*]] = alloca %struct.S, i64 1, align 4 // LLVM: [[TMP1:%.*]] = getelementptr %struct.S, ptr [[TMP0]], i32 0, i32 0 -// LLVM: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8 +// LLVM: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4 // LLVM: [[TMP3:%.*]] = shl i64 [[TMP2]], 15 // LLVM: [[TMP4:%.*]] = ashr i64 [[TMP3]], 47 // LLVM: [[TMP5:%.*]] = trunc i64 [[TMP4]] to i32 // LLVM: [[TMP6:%.*]] = getelementptr %struct.S, ptr [[TMP0]], i32 0, i32 0 // LLVM: [[TMP7:%.*]] = zext i32 [[TMP5]] to i64 -// LLVM: [[TMP8:%.*]] = load i64, ptr [[TMP6]], align 8 +// LLVM: [[TMP8:%.*]] = load i64, ptr [[TMP6]], align 4 // LLVM: [[TMP9:%.*]] = and i64 [[TMP7]], 15 // LLVM: [[TMP10:%.*]] = and i64 [[TMP8]], -16 // LLVM: [[TMP11:%.*]] = or i64 [[TMP10]], [[TMP9]] -// LLVM: store i64 [[TMP11]], ptr [[TMP6]], align 8 +// LLVM: store i64 [[TMP11]], ptr [[TMP6]], align 4 // LLVM: [[TMP12:%.*]] = shl i64 [[TMP9]], 60 // LLVM: [[TMP13:%.*]] = ashr i64 [[TMP12]], 60 // LLVM: [[TMP15:%.*]] = trunc i64 [[TMP13]] to i32 @@ -222,16 +222,16 @@ void get_volatile(V* v) { // CIR: [[TMP1:%.*]] = cir.const #cir.int<3> : !s32i // CIR: [[TMP2:%.*]] = cir.load align(8) [[TMP0]] : !cir.ptr>, !cir.ptr // CIR: [[TMP3:%.*]] = cir.get_member [[TMP2]][0] {name = "b"} : !cir.ptr -> !cir.ptr -// CIR: [[TMP4:%.*]] = cir.set_bitfield(#bfi_b, [[TMP3]] : !cir.ptr, [[TMP1]] : !s32i) {is_volatile} -> !s32i +// CIR: [[TMP4:%.*]] = cir.set_bitfield align(4) (#bfi_b, [[TMP3]] : !cir.ptr, [[TMP1]] : !s32i) {is_volatile} -> !s32i // LLVM: define dso_local void @get_volatile // LLVM: [[TMP0:%.*]] = alloca ptr, i64 1, align 8 // LLVM: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8 // LLVM: [[TMP2:%.*]] = getelementptr %struct.V, ptr [[TMP1]], i32 0, i32 0 -// LLVM: [[TMP3:%.*]] = load volatile i64, ptr [[TMP2]], align 8 +// LLVM: [[TMP3:%.*]] = load volatile i64, ptr [[TMP2]], align 4 // LLVM: [[TMP4:%.*]] = and i64 [[TMP3]], -1095216660481 // LLVM: [[TMP5:%.*]] = or i64 [[TMP4]], 12884901888 -// LLVM: store volatile i64 [[TMP5]], ptr [[TMP2]], align 8 +// LLVM: store volatile i64 [[TMP5]], ptr [[TMP2]], align 4 // OCGC: define dso_local void @get_volatile // OCGC: [[TMP0:%.*]] = alloca ptr, align 8 @@ -249,16 +249,16 @@ void set_volatile(V* v) { //CIR: [[TMP1:%.*]] = cir.const #cir.int<3> : !s32i //CIR: [[TMP2:%.*]] = cir.load align(8) [[TMP0]] : !cir.ptr>, !cir.ptr //CIR: [[TMP3:%.*]] = cir.get_member [[TMP2]][0] {name = "b"} : !cir.ptr -> !cir.ptr -//CIR: [[TMP4:%.*]] = cir.set_bitfield(#bfi_b, [[TMP3]] : !cir.ptr, [[TMP1]] : !s32i) {is_volatile} -> !s32i +//CIR: [[TMP4:%.*]] = cir.set_bitfield align(4) (#bfi_b, [[TMP3]] : !cir.ptr, [[TMP1]] : !s32i) {is_volatile} -> !s32i // LLVM: define dso_local void @set_volatile // LLVM: [[TMP0:%.*]] = alloca ptr, i64 1, align 8 // LLVM: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8 // LLVM: [[TMP2:%.*]] = getelementptr %struct.V, ptr [[TMP1]], i32 0, i32 0 -// LLVM: [[TMP3:%.*]] = load volatile i64, ptr [[TMP2]], align 8 +// LLVM: [[TMP3:%.*]] = load volatile i64, ptr [[TMP2]], align 4 // LLVM: [[TMP4:%.*]] = and i64 [[TMP3]], -1095216660481 // LLVM: [[TMP5:%.*]] = or i64 [[TMP4]], 12884901888 -// LLVM: store volatile i64 [[TMP5]], ptr [[TMP2]], align 8 +// LLVM: store volatile i64 [[TMP5]], ptr [[TMP2]], align 4 // OGCG: define dso_local void @set_volatile // OGCG: [[TMP0:%.*]] = alloca ptr, align 8 @@ -276,24 +276,24 @@ void unOp(S* s) { // CIR: [[TMP0:%.*]] = cir.alloca !cir.ptr, !cir.ptr>, ["s", init] {alignment = 8 : i64} // CIR: [[TMP1:%.*]] = cir.load align(8) [[TMP0]] : !cir.ptr>, !cir.ptr // CIR: [[TMP2:%.*]] = cir.get_member [[TMP1]][0] {name = "d"} : !cir.ptr -> !cir.ptr -// CIR: [[TMP3:%.*]] = cir.get_bitfield(#bfi_d, [[TMP2]] : !cir.ptr) -> !s32i +// CIR: [[TMP3:%.*]] = cir.get_bitfield align(4) (#bfi_d, [[TMP2]] : !cir.ptr) -> !s32i // CIR: [[TMP4:%.*]] = cir.unary(inc, [[TMP3]]) nsw : !s32i, !s32i -// CIR: cir.set_bitfield(#bfi_d, [[TMP2]] : !cir.ptr, [[TMP4]] : !s32i) +// CIR: cir.set_bitfield align(4) (#bfi_d, [[TMP2]] : !cir.ptr, [[TMP4]] : !s32i) // LLVM: define {{.*@unOp}} // LLVM: [[TMP0:%.*]] = getelementptr %struct.S, ptr [[LOAD0:%.*]], i32 0, i32 0 -// LLVM: [[TMP1:%.*]] = load i64, ptr [[TMP0]], align 8 +// LLVM: [[TMP1:%.*]] = load i64, ptr [[TMP0]], align 4 // LLVM: [[TMP2:%.*]] = shl i64 [[TMP1]], 13 // LLVM: [[TMP3:%.*]] = ashr i64 [[TMP2]], 62 // LLVM: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 // LLVM: [[TMP5:%.*]] = add nsw i32 [[TMP4]], 1 // LLVM: [[TMP6:%.*]] = zext i32 [[TMP5]] to i64 -// LLVM: [[TMP7:%.*]] = load i64, ptr [[TMP0]], align 8 +// LLVM: [[TMP7:%.*]] = load i64, ptr [[TMP0]], align 4 // LLVM: [[TMP8:%.*]] = and i64 [[TMP6]], 3 // LLVM: [[TMP9:%.*]] = shl i64 [[TMP8]], 49 // LLVM: [[TMP10:%.*]] = and i64 [[TMP7]], -1688849860263937 // LLVM: [[TMP11:%.*]] = or i64 [[TMP10]], [[TMP9]] -// LLVM: store i64 [[TMP11]], ptr [[TMP0]], align 8 +// LLVM: store i64 [[TMP11]], ptr [[TMP0]], align 4 // LLVM: [[TMP12:%.*]] = shl i64 [[TMP8]], 62 // LLVM: [[TMP13:%.*]] = ashr i64 [[TMP12]], 62 // LLVM: [[TMP14:%.*]] = trunc i64 [[TMP13]] to i32 diff --git a/clang/test/CIR/CodeGen/bitfields.cpp b/clang/test/CIR/CodeGen/bitfields.cpp index 6715ebf1f48b6..7650e0b83faf6 100644 --- a/clang/test/CIR/CodeGen/bitfields.cpp +++ b/clang/test/CIR/CodeGen/bitfields.cpp @@ -39,14 +39,14 @@ int load_field(S* s) { // CIR: [[TMP0:%.*]] = cir.alloca !cir.ptr, !cir.ptr>, ["s", init] // CIR: [[TMP1:%.*]] = cir.load{{.*}} [[TMP0]] : !cir.ptr>, !cir.ptr // CIR: [[TMP2:%.*]] = cir.get_member [[TMP1]][0] {name = "c"} : !cir.ptr -> !cir.ptr -// CIR: [[TMP3:%.*]] = cir.get_bitfield(#bfi_c, [[TMP2]] : !cir.ptr) -> !s32i +// CIR: [[TMP3:%.*]] = cir.get_bitfield align(4) (#bfi_c, [[TMP2]] : !cir.ptr) -> !s32i // LLVM: define dso_local i32 @_Z10load_fieldP1S // LLVM: [[TMP0:%.*]] = alloca ptr, i64 1, align 8 // LLVM: [[TMP1:%.*]] = alloca i32, i64 1, align 4 // LLVM: [[TMP2:%.*]] = load ptr, ptr [[TMP0]], align 8 // LLVM: [[TMP3:%.*]] = getelementptr %struct.S, ptr [[TMP2]], i32 0, i32 0 -// LLVM: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8 +// LLVM: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 4 // LLVM: [[TMP5:%.*]] = shl i64 [[TMP4]], 15 // LLVM: [[TMP6:%.*]] = ashr i64 [[TMP5]], 47 // LLVM: [[TMP7:%.*]] = trunc i64 [[TMP6]] to i32 @@ -67,15 +67,15 @@ void store_field() { // CIR: [[TMP0:%.*]] = cir.alloca !rec_S, !cir.ptr // CIR: [[TMP1:%.*]] = cir.const #cir.int<3> : !s32i // CIR: [[TMP2:%.*]] = cir.get_member [[TMP0]][0] {name = "a"} : !cir.ptr -> !cir.ptr -// CIR: cir.set_bitfield(#bfi_a, [[TMP2]] : !cir.ptr, [[TMP1]] : !s32i) +// CIR: cir.set_bitfield align(4) (#bfi_a, [[TMP2]] : !cir.ptr, [[TMP1]] : !s32i) // LLVM: define dso_local void @_Z11store_fieldv // LLVM: [[TMP0:%.*]] = alloca %struct.S, i64 1, align 4 // LLVM: [[TMP1:%.*]] = getelementptr %struct.S, ptr [[TMP0]], i32 0, i32 0 -// LLVM: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8 +// LLVM: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4 // LLVM: [[TMP3:%.*]] = and i64 [[TMP2]], -16 // LLVM: [[TMP4:%.*]] = or i64 [[TMP3]], 3 -// LLVM: store i64 [[TMP4]], ptr [[TMP1]], align 8 +// LLVM: store i64 [[TMP4]], ptr [[TMP1]], align 4 // OGCG: define dso_local void @_Z11store_fieldv() // OGCG: [[TMP0:%.*]] = alloca %struct.S, align 4 @@ -93,25 +93,25 @@ void store_bitfield_to_bitfield(S* s) { // CIR: [[TMP1:%.*]] = cir.const #cir.int<3> : !s32i // CIR: [[TMP2:%.*]] = cir.load align(8) [[TMP0]] : !cir.ptr>, !cir.ptr // CIR: [[TMP3:%.*]] = cir.get_member [[TMP2]][0] {name = "b"} : !cir.ptr -> !cir.ptr -// CIR: [[TMP4:%.*]] = cir.set_bitfield(#bfi_b, [[TMP3]] : !cir.ptr, [[TMP1]] : !s32i) -> !s32i +// CIR: [[TMP4:%.*]] = cir.set_bitfield align(4) (#bfi_b, [[TMP3]] : !cir.ptr, [[TMP1]] : !s32i) -> !s32i // CIR: [[TMP5:%.*]] = cir.load align(8) [[TMP0]] : !cir.ptr>, !cir.ptr // CIR: [[TMP6:%.*]] = cir.get_member [[TMP5]][0] {name = "a"} : !cir.ptr -> !cir.ptr -// CIR: [[TMP7:%.*]] = cir.set_bitfield(#bfi_a, [[TMP6]] : !cir.ptr, [[TMP4]] : !s32i) -> !s32i +// CIR: [[TMP7:%.*]] = cir.set_bitfield align(4) (#bfi_a, [[TMP6]] : !cir.ptr, [[TMP4]] : !s32i) -> !s32i // LLVM: define dso_local void @_Z26store_bitfield_to_bitfieldP1S // LLVM: [[TMP0:%.*]] = alloca ptr, i64 1, align 8 // LLVM: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8 // LLVM: [[TMP2:%.*]] = getelementptr %struct.S, ptr [[TMP1]], i32 0, i32 0 -// LLVM: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 8 +// LLVM: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 4 // LLVM: [[TMP4:%.*]] = and i64 [[TMP3]], -2147483633 // LLVM: [[TMP5:%.*]] = or i64 [[TMP4]], 48 -// LLVM: store i64 [[TMP5]], ptr [[TMP2]], align 8 +// LLVM: store i64 [[TMP5]], ptr [[TMP2]], align 4 // LLVM: [[TMP6:%.*]] = load ptr, ptr [[TMP0]], align 8 // LLVM: [[TMP7:%.*]] = getelementptr %struct.S, ptr [[TMP6]], i32 0, i32 0 -// LLVM: [[TMP8:%.*]] = load i64, ptr [[TMP7]], align 8 +// LLVM: [[TMP8:%.*]] = load i64, ptr [[TMP7]], align 4 // LLVM: [[TMP9:%.*]] = and i64 [[TMP8]], -16 // LLVM: [[TMP10:%.*]] = or i64 [[TMP9]], 3 -// LLVM: store i64 [[TMP10]], ptr [[TMP7]], align 8 +// LLVM: store i64 [[TMP10]], ptr [[TMP7]], align 4 // OGCG: define dso_local void @_Z26store_bitfield_to_bitfieldP1S // OGCG: [[TMP0:%.*]] = alloca ptr, align 8 diff --git a/clang/test/CIR/CodeGen/bitfields_be.c b/clang/test/CIR/CodeGen/bitfields_be.c index 6133927b67d21..77741ba74870b 100644 --- a/clang/test/CIR/CodeGen/bitfields_be.c +++ b/clang/test/CIR/CodeGen/bitfields_be.c @@ -25,7 +25,7 @@ int init(S* s) { //CIR: [[TMP0:%.*]] = cir.alloca !cir.ptr, !cir.ptr>, ["s", init] {alignment = 8 : i64} //CIR: [[TMP1:%.*]] = cir.load align(8) [[TMP0]] : !cir.ptr>, !cir.ptr //CIR: [[TMP2:%.*]] = cir.get_member [[TMP1]][0] {name = "c"} : !cir.ptr -> !cir.ptr -//CIR: [[TMP3:%.*]] = cir.get_bitfield(#bfi_c, [[TMP2]] : !cir.ptr) -> !s32i +//CIR: [[TMP3:%.*]] = cir.get_bitfield align(4) (#bfi_c, [[TMP2]] : !cir.ptr) -> !s32i //LLVM: define dso_local i32 @init(ptr %0) { //LLVM: [[TMP0:%.*]] = alloca ptr, i64 1, align 8 @@ -57,7 +57,7 @@ void load(S* s) { // CIR: %[[MIN1:.*]] = cir.unary(minus, %[[CONST1]]) nsw : !s32i, !s32i // CIR: %[[VAL0:.*]] = cir.load align(8) %[[PTR0]] : !cir.ptr>, !cir.ptr // CIR: %[[GET0:.*]] = cir.get_member %[[VAL0]][0] {name = "a"} : !cir.ptr -> !cir.ptr -// CIR: %[[SET0:.*]] = cir.set_bitfield(#bfi_a, %[[GET0]] : !cir.ptr, %[[MIN1]] : !s32i) -> !s32i +// CIR: %[[SET0:.*]] = cir.set_bitfield align(4) (#bfi_a, %[[GET0]] : !cir.ptr, %[[MIN1]] : !s32i) -> !s32i // LLVM: define dso_local void @load // LLVM: %[[PTR0:.*]] = load ptr @@ -65,50 +65,50 @@ void load(S* s) { // LLVM: %[[VAL0:.*]] = load i32, ptr %[[GET0]], align 4 // LLVM: %[[AND0:.*]] = and i32 %[[VAL0]], 268435455 // LLVM: %[[OR0:.*]] = or i32 %[[AND0]], -1073741824 -// LLVM: store i32 %[[OR0]], ptr %[[GET0]] +// LLVM: store i32 %[[OR0]], ptr %[[GET0]], align 4 // OGCG: define dso_local void @load // OGCG: %[[PTR0:.*]] = load ptr -// OGCG: %[[VAL0:.*]] = load i32, ptr %[[PTR0]] +// OGCG: %[[VAL0:.*]] = load i32, ptr %[[PTR0]], align 4 // OGCG: %[[AND0:.*]] = and i32 %[[VAL0]], 268435455 // OGCG: %[[OR0:.*]] = or i32 %[[AND0]], -1073741824 -// OGCG: store i32 %[[OR0]], ptr %[[PTR0]] +// OGCG: store i32 %[[OR0]], ptr %[[PTR0]], align 4 // field 'b' // CIR: %[[CONST2:.*]] = cir.const #cir.int<42> : !s32i // CIR: %[[VAL1:.*]] = cir.load align(8) %[[PTR0]] : !cir.ptr>, !cir.ptr // CIR: %[[GET1:.*]] = cir.get_member %[[VAL1]][0] {name = "b"} : !cir.ptr -> !cir.ptr -// CIR: %[[SET1:.*]] = cir.set_bitfield(#bfi_b, %[[GET1]] : !cir.ptr, %[[CONST2]] : !s32i) -> !s32i +// CIR: %[[SET1:.*]] = cir.set_bitfield align(4) (#bfi_b, %[[GET1]] : !cir.ptr, %[[CONST2]] : !s32i) -> !s32i // LLVM: %[[PTR1:.*]] = load ptr // LLVM: %[[GET1:.*]] = getelementptr %struct.S, ptr %[[PTR1]], i32 0, i32 0 // LLVM: %[[VAL1:.*]] = load i32, ptr %[[GET1]], align 4 // LLVM: %[[AND1:.*]] = and i32 %[[VAL1]], -268304385 // LLVM: %[[OR1:.*]] = or i32 %[[AND1]], 5505024 -// LLVM: store i32 %[[OR1]], ptr %[[GET1]] +// LLVM: store i32 %[[OR1]], ptr %[[GET1]], align 4 // OGCG: %[[PTR1:.*]] = load ptr -// OGCG: %[[VAL1:.*]] = load i32, ptr %[[PTR1]] +// OGCG: %[[VAL1:.*]] = load i32, ptr %[[PTR1]], align 4 // OGCG: %[[AND1:.*]] = and i32 %[[VAL1]], -268304385 // OGCG: %[[OR1:.*]] = or i32 %[[AND1]], 5505024 -// OGCG: store i32 %[[OR1]], ptr %[[PTR1]] +// OGCG: store i32 %[[OR1]], ptr %[[PTR1]], align 4 // field 'c' // CIR: %[[CONST3:.*]] = cir.const #cir.int<12345> : !s32i // CIR: %[[MIN2:.*]] = cir.unary(minus, %[[CONST3]]) nsw : !s32i, !s32i // CIR: %[[VAL2:.*]] = cir.load align(8) %[[PTR0]] : !cir.ptr>, !cir.ptr // CIR: %[[GET2:.*]] = cir.get_member %[[VAL2]][0] {name = "c"} : !cir.ptr -> !cir.ptr -// CIR: %[[SET2:.*]] = cir.set_bitfield(#bfi_c, %[[GET2]] : !cir.ptr, %[[MIN2]] : !s32i) -> !s32i +// CIR: %[[SET2:.*]] = cir.set_bitfield align(4) (#bfi_c, %[[GET2]] : !cir.ptr, %[[MIN2]] : !s32i) -> !s32i // LLVM: %[[PTR2:.*]] = load ptr // LLVM: %[[GET2:.*]] = getelementptr %struct.S, ptr %[[PTR2]], i32 0, i32 0 // LLVM: %[[VAL2:.*]] = load i32, ptr %[[GET2]], align 4 // LLVM: %[[AND2:.*]] = and i32 %[[VAL2]], -131072 // LLVM: %[[OR2:.*]] = or i32 %[[AND2]], 118727 -// LLVM: store i32 %[[OR2]], ptr %[[GET2]] +// LLVM: store i32 %[[OR2]], ptr %[[GET2]], align 4 // OGCG: %[[PTR2:.*]] = load ptr -// OGCG: %[[VAL2:.*]] = load i32, ptr %[[PTR2]] +// OGCG: %[[VAL2:.*]] = load i32, ptr %[[PTR2]], align 4 // OGCG: %[[AND2:.*]] = and i32 %[[VAL2]], -131072 // OGCG: %[[OR2:.*]] = or i32 %[[AND2]], 118727 -// OGCG: store i32 %[[OR2]], ptr %[[PTR2]] +// OGCG: store i32 %[[OR2]], ptr %[[PTR2]], align 4 diff --git a/clang/test/CIR/CodeGen/builtin_bit.cpp b/clang/test/CIR/CodeGen/builtin_bit.cpp index f017b6eb51971..4ac82bd749e8a 100644 --- a/clang/test/CIR/CodeGen/builtin_bit.cpp +++ b/clang/test/CIR/CodeGen/builtin_bit.cpp @@ -416,3 +416,141 @@ unsigned long long test_builtin_bswap64(unsigned long long x) { // OGCG-LABEL: @_Z20test_builtin_bswap64y // OGCG: %{{.+}} = call i64 @llvm.bswap.i64(i64 %{{.+}}) + +unsigned char test_builtin_rotateleft8(unsigned char x, unsigned char y) { + return __builtin_rotateleft8(x, y); +} + +// CIR-LABEL: @_Z24test_builtin_rotateleft8hh +// CIR: %{{.+}} = cir.rotate left %{{.+}}, %{{.+}} : !u8i + +// LLVM-LABEL: @_Z24test_builtin_rotateleft8hh +// LLVM: %[[INPUT:.+]] = load i8, ptr %{{.+}}, align 1 +// LLVM-NEXT: %[[AMOUNT:.+]] = load i8, ptr %{{.+}}, align 1 +// LLVM-NEXT: %{{.+}} = call i8 @llvm.fshl.i8(i8 %[[INPUT]], i8 %[[INPUT]], i8 %[[AMOUNT]]) + +// OGCG-LABEL: @_Z24test_builtin_rotateleft8hh +// OGCG: %[[INPUT:.+]] = load i8, ptr %{{.+}}, align 1 +// OGCG-NEXT: %[[AMOUNT:.+]] = load i8, ptr %{{.+}}, align 1 +// OGCG-NEXT: %{{.+}} = call i8 @llvm.fshl.i8(i8 %[[INPUT]], i8 %[[INPUT]], i8 %[[AMOUNT]]) + +unsigned short test_builtin_rotateleft16(unsigned short x, unsigned short y) { + return __builtin_rotateleft16(x, y); +} + +// CIR-LABEL: @_Z25test_builtin_rotateleft16tt +// CIR: %{{.+}} = cir.rotate left %{{.+}}, %{{.+}} : !u16i + +// LLVM-LABEL: @_Z25test_builtin_rotateleft16tt +// LLVM: %[[INPUT:.+]] = load i16, ptr %{{.+}}, align 2 +// LLVM-NEXT: %[[AMOUNT:.+]] = load i16, ptr %{{.+}}, align 2 +// LLVM-NEXT: %{{.+}} = call i16 @llvm.fshl.i16(i16 %[[INPUT]], i16 %[[INPUT]], i16 %[[AMOUNT]]) + +// OGCG-LABEL: @_Z25test_builtin_rotateleft16tt +// OGCG: %[[INPUT:.+]] = load i16, ptr %{{.+}}, align 2 +// OGCG-NEXT: %[[AMOUNT:.+]] = load i16, ptr %{{.+}}, align 2 +// OGCG-NEXT: %{{.+}} = call i16 @llvm.fshl.i16(i16 %[[INPUT]], i16 %[[INPUT]], i16 %[[AMOUNT]]) + +unsigned test_builtin_rotateleft32(unsigned x, unsigned y) { + return __builtin_rotateleft32(x, y); +} + +// CIR-LABEL: @_Z25test_builtin_rotateleft32jj +// CIR: %{{.+}} = cir.rotate left %{{.+}}, %{{.+}} : !u32i + +// LLVM-LABEL: @_Z25test_builtin_rotateleft32jj +// LLVM: %[[INPUT:.+]] = load i32, ptr %{{.+}}, align 4 +// LLVM-NEXT: %[[AMOUNT:.+]] = load i32, ptr %{{.+}}, align 4 +// LLVM-NEXT: %{{.+}} = call i32 @llvm.fshl.i32(i32 %[[INPUT]], i32 %[[INPUT]], i32 %[[AMOUNT]]) + +// OGCG-LABEL: @_Z25test_builtin_rotateleft32jj +// OGCG: %[[INPUT:.+]] = load i32, ptr %{{.+}}, align 4 +// OGCG-NEXT: %[[AMOUNT:.+]] = load i32, ptr %{{.+}}, align 4 +// OGCG-NEXT: %{{.+}} = call i32 @llvm.fshl.i32(i32 %[[INPUT]], i32 %[[INPUT]], i32 %[[AMOUNT]]) + +unsigned long long test_builtin_rotateleft64(unsigned long long x, + unsigned long long y) { + return __builtin_rotateleft64(x, y); +} + +// CIR-LABEL: @_Z25test_builtin_rotateleft64yy +// CIR: %{{.+}} = cir.rotate left %{{.+}}, %{{.+}} : !u64i + +// LLVM-LABEL: @_Z25test_builtin_rotateleft64yy +// LLVM: %[[INPUT:.+]] = load i64, ptr %{{.+}}, align 8 +// LLVM-NEXT: %[[AMOUNT:.+]] = load i64, ptr %{{.+}}, align 8 +// LLVM-NEXT: %{{.+}} = call i64 @llvm.fshl.i64(i64 %[[INPUT]], i64 %[[INPUT]], i64 %[[AMOUNT]]) + +// OGCG-LABEL: @_Z25test_builtin_rotateleft64yy +// OGCG: %[[INPUT:.+]] = load i64, ptr %{{.+}}, align 8 +// OGCG-NEXT: %[[AMOUNT:.+]] = load i64, ptr %{{.+}}, align 8 +// OGCG-NEXT: %{{.+}} = call i64 @llvm.fshl.i64(i64 %[[INPUT]], i64 %[[INPUT]], i64 %[[AMOUNT]]) + +unsigned char test_builtin_rotateright8(unsigned char x, unsigned char y) { + return __builtin_rotateright8(x, y); +} + +// CIR-LABEL: @_Z25test_builtin_rotateright8hh +// CIR: %{{.+}} = cir.rotate right %{{.+}}, %{{.+}} : !u8i + +// LLVM-LABEL: @_Z25test_builtin_rotateright8hh +// LLVM: %[[INPUT:.+]] = load i8, ptr %{{.+}}, align 1 +// LLVM-NEXT: %[[AMOUNT:.+]] = load i8, ptr %{{.+}}, align 1 +// LLVM-NEXT: %{{.+}} = call i8 @llvm.fshr.i8(i8 %[[INPUT]], i8 %[[INPUT]], i8 %[[AMOUNT]]) + +// OGCG-LABEL: @_Z25test_builtin_rotateright8hh +// OGCG: %[[INPUT:.+]] = load i8, ptr %{{.+}}, align 1 +// OGCG-NEXT: %[[AMOUNT:.+]] = load i8, ptr %{{.+}}, align 1 +// OGCG-NEXT: %{{.+}} = call i8 @llvm.fshr.i8(i8 %[[INPUT]], i8 %[[INPUT]], i8 %[[AMOUNT]]) + +unsigned short test_builtin_rotateright16(unsigned short x, unsigned short y) { + return __builtin_rotateright16(x, y); +} + +// CIR-LABEL: @_Z26test_builtin_rotateright16tt +// CIR: %{{.+}} = cir.rotate right %{{.+}}, %{{.+}} : !u16i + +// LLVM-LABEL: @_Z26test_builtin_rotateright16tt +// LLVM: %[[INPUT:.+]] = load i16, ptr %{{.+}}, align 2 +// LLVM-NEXT: %[[AMOUNT:.+]] = load i16, ptr %{{.+}}, align 2 +// LLVM-NEXT: %{{.+}} = call i16 @llvm.fshr.i16(i16 %[[INPUT]], i16 %[[INPUT]], i16 %[[AMOUNT]]) + +// OGCG-LABEL: @_Z26test_builtin_rotateright16tt +// OGCG: %[[INPUT:.+]] = load i16, ptr %{{.+}}, align 2 +// OGCG-NEXT: %[[AMOUNT:.+]] = load i16, ptr %{{.+}}, align 2 +// OGCG-NEXT: %{{.+}} = call i16 @llvm.fshr.i16(i16 %[[INPUT]], i16 %[[INPUT]], i16 %[[AMOUNT]]) + +unsigned test_builtin_rotateright32(unsigned x, unsigned y) { + return __builtin_rotateright32(x, y); +} + +// CIR-LABEL: @_Z26test_builtin_rotateright32jj +// CIR: %{{.+}} = cir.rotate right %{{.+}}, %{{.+}} : !u32i + +// LLVM-LABEL: @_Z26test_builtin_rotateright32jj +// LLVM: %[[INPUT:.+]] = load i32, ptr %{{.+}}, align 4 +// LLVM-NEXT: %[[AMOUNT:.+]] = load i32, ptr %{{.+}}, align 4 +// LLVM-NEXT: %{{.+}} = call i32 @llvm.fshr.i32(i32 %[[INPUT]], i32 %[[INPUT]], i32 %[[AMOUNT]]) + +// OGCG-LABEL: @_Z26test_builtin_rotateright32jj +// OGCG: %[[INPUT:.+]] = load i32, ptr %{{.+}}, align 4 +// OGCG-NEXT: %[[AMOUNT:.+]] = load i32, ptr %{{.+}}, align 4 +// OGCG-NEXT: %{{.+}} = call i32 @llvm.fshr.i32(i32 %[[INPUT]], i32 %[[INPUT]], i32 %[[AMOUNT]]) + +unsigned long long test_builtin_rotateright64(unsigned long long x, + unsigned long long y) { + return __builtin_rotateright64(x, y); +} + +// CIR-LABEL: @_Z26test_builtin_rotateright64yy +// CIR: %{{.+}} = cir.rotate right %{{.+}}, %{{.+}} : !u64i + +// LLVM-LABEL: @_Z26test_builtin_rotateright64yy +// LLVM: %[[INPUT:.+]] = load i64, ptr %{{.+}}, align 8 +// LLVM-NEXT: %[[AMOUNT:.+]] = load i64, ptr %{{.+}}, align 8 +// LLVM-NEXT: %{{.+}} = call i64 @llvm.fshr.i64(i64 %[[INPUT]], i64 %[[INPUT]], i64 %[[AMOUNT]]) + +// OGCG-LABEL: @_Z26test_builtin_rotateright64yy +// OGCG: %[[INPUT:.+]] = load i64, ptr %{{.+}}, align 8 +// OGCG-NEXT: %[[AMOUNT:.+]] = load i64, ptr %{{.+}}, align 8 +// OGCG-NEXT: %{{.+}} = call i64 @llvm.fshr.i64(i64 %[[INPUT]], i64 %[[INPUT]], i64 %[[AMOUNT]]) diff --git a/clang/test/CIR/CodeGen/builtin_call.cpp b/clang/test/CIR/CodeGen/builtin_call.cpp index ad0e478040836..d9a70683a4dbc 100644 --- a/clang/test/CIR/CodeGen/builtin_call.cpp +++ b/clang/test/CIR/CodeGen/builtin_call.cpp @@ -111,6 +111,22 @@ void assume(bool arg) { // OGCG: call void @llvm.assume(i1 %{{.+}}) // OGCG: } +void assume_separate_storage(void *p1, void *p2) { + __builtin_assume_separate_storage(p1, p2); +} + +// CIR: cir.func{{.*}} @_Z23assume_separate_storagePvS_ +// CIR: cir.assume_separate_storage %{{.+}}, %{{.+}} : !cir.ptr +// CIR: } + +// LLVM: define {{.*}}void @_Z23assume_separate_storagePvS_ +// LLVM: call void @llvm.assume(i1 true) [ "separate_storage"(ptr %{{.+}}, ptr %{{.+}}) ] +// LLVM: } + +// OGCG: define {{.*}}void @_Z23assume_separate_storagePvS_ +// OGCG: call void @llvm.assume(i1 true) [ "separate_storage"(ptr %{{.+}}, ptr %{{.+}}) ] +// OGCG: } + void expect(int x, int y) { __builtin_expect(x, y); } diff --git a/clang/test/CIR/CodeGen/complex-builtins.cpp b/clang/test/CIR/CodeGen/complex-builtins.cpp index f0d12d0ef6663..811af47a704f5 100644 --- a/clang/test/CIR/CodeGen/complex-builtins.cpp +++ b/clang/test/CIR/CodeGen/complex-builtins.cpp @@ -83,3 +83,39 @@ void foo3() { // OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[COMPLEX]], i32 0, i32 1 // OGCG: %[[A_IMAG:.*]] = load double, ptr %[[A_IMAG_PTR]], align 8 // OGCG: store double %[[A_IMAG]], ptr %[[INIT]], align 8 + +void foo4() { + float _Complex a; + float _Complex b = __builtin_conjf(a); +} + +// CIR: %[[COMPLEX:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["a"] +// CIR: %[[RESULT:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["b", init] +// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[COMPLEX]] : !cir.ptr>, !cir.complex +// CIR: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex -> !cir.float +// CIR: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : !cir.complex -> !cir.float +// CIR: %[[IMAG_MINUS:.*]] = cir.unary(minus, %[[IMAG]]) : !cir.float, !cir.float +// CIR: %[[RESULT_VAL:.*]] = cir.complex.create %[[REAL]], %[[IMAG_MINUS]] : !cir.float -> !cir.complex +// CIR: cir.store{{.*}} %[[RESULT_VAL]], %[[RESULT]] : !cir.complex, !cir.ptr> + +// LLVM: %[[COMPLEX:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[RESULT:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[TMP:.*]] = load { float, float }, ptr %[[COMPLEX]], align 4 +// LLVM: %[[REAL:.*]] = extractvalue { float, float } %[[TMP]], 0 +// LLVM: %[[IMAG:.*]] = extractvalue { float, float } %[[TMP]], 1 +// LLVM: %[[IMAG_MINUS:.*]] = fneg float %[[IMAG]] +// LLVM: %[[RESULT_TMP:.*]] = insertvalue { float, float } {{.*}}, float %[[REAL]], 0 +// LLVM: %[[RESULT_VAL:.*]] = insertvalue { float, float } %[[RESULT_TMP]], float %[[IMAG_MINUS]], 1 +// LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[RESULT]], align 4 + +// OGCG: %[[COMPLEX:.*]] = alloca { float, float }, align 4 +// OGCG: %[[RESULT:.*]] = alloca { float, float }, align 4 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 0 +// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX]], i32 0, i32 1 +// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4 +// OGCG: %[[A_IMAG_MINUS:.*]] = fneg float %[[A_IMAG]] +// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT]], i32 0, i32 0 +// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[RESULT]], i32 0, i32 1 +// OGCG: store float %[[A_REAL]], ptr %[[RESULT_REAL_PTR]], align 4 +// OGCG: store float %[[A_IMAG_MINUS]], ptr %[[RESULT_IMAG_PTR]], align 4 diff --git a/clang/test/CIR/CodeGen/complex-unary.cpp b/clang/test/CIR/CodeGen/complex-unary.cpp new file mode 100644 index 0000000000000..676b5546d28e0 --- /dev/null +++ b/clang/test/CIR/CodeGen/complex-unary.cpp @@ -0,0 +1,286 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-canonicalize -o %t.cir %s 2>&1 | FileCheck --check-prefix=CIR-BEFORE %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-after=cir-lowering-prepare -o %t.cir %s 2>&1 | FileCheck --check-prefixes=CIR-AFTER %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG + +void foo() { + int _Complex a; + int _Complex b = ~a; +} + +// CIR-BEFORE: %[[A_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["a"] +// CIR-BEFORE: %[[B_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["b", init] +// CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr>, !cir.complex +// CIR-BEFORE: %[[COMPLEX_NOT:.*]] = cir.unary(not, %[[TMP]]) : !cir.complex, !cir.complex +// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_NOT]], %[[B_ADDR]] : !cir.complex, !cir.ptr> + +// CIR-AFTER: %[[A_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["a"] +// CIR-AFTER: %[[B_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["b", init] +// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr>, !cir.complex +// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex -> !s32i +// CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : !cir.complex -> !s32i +// CIR-AFTER: %[[IMAG_MINUS:.*]] = cir.unary(minus, %[[IMAG]]) : !s32i, !s32i +// CIR-AFTER: %[[RESULT_VAL:.*]] = cir.complex.create %[[REAL]], %[[IMAG_MINUS]] : !s32i -> !cir.complex +// CIR-AFTER: cir.store{{.*}} %[[RESULT_VAL]], %[[B_ADDR]] : !cir.complex, !cir.ptr> + +// LLVM: %[[A_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4 +// LLVM: %[[B_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4 +// LLVM: %[[TMP:.*]] = load { i32, i32 }, ptr %[[A_ADDR]], align 4 +// LLVM: %[[REAL:.*]] = extractvalue { i32, i32 } %[[TMP]], 0 +// LLVM: %[[IMAG:.*]] = extractvalue { i32, i32 } %[[TMP]], 1 +// LLVM: %[[IMAG_MINUS:.*]] = sub i32 0, %[[IMAG]] +// LLVM: %[[RESULT_TMP:.*]] = insertvalue { i32, i32 } {{.*}}, i32 %[[REAL]], 0 +// LLVM: %[[RESULT_VAL:.*]] = insertvalue { i32, i32 } %[[RESULT_TMP]], i32 %[[IMAG_MINUS]], 1 +// LLVM: store { i32, i32 } %[[RESULT_VAL]], ptr %[[B_ADDR]], align 4 + +// OGCG: %[[A_ADDR:.*]] = alloca { i32, i32 }, align 4 +// OGCG: %[[B_ADDR:.*]] = alloca { i32, i32 }, align 4 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: %[[A_REAL:.*]] = load i32, ptr %[[A_REAL_PTR]], align 4 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: %[[A_IMAG:.*]] = load i32, ptr %[[A_IMAG_PTR]], align 4 +// OGCG: %[[A_IMAG_MINUS:.*]] = sub i32 0, %[[A_IMAG]] +// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[B_ADDR]], i32 0, i32 0 +// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[B_ADDR]], i32 0, i32 1 +// OGCG: store i32 %[[A_REAL]], ptr %[[RESULT_REAL_PTR]], align 4 +// OGCG: store i32 %[[A_IMAG_MINUS]], ptr %[[RESULT_IMAG_PTR]], align 4 + +void foo2() { + float _Complex a; + float _Complex b = ~a; +} + +// CIR-BEFORE: %[[A_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["a"] +// CIR-BEFORE: %[[B_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["b", init] +// CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr>, !cir.complex +// CIR-BEFORE: %[[COMPLEX_NOT:.*]] = cir.unary(not, %[[TMP]]) : !cir.complex, !cir.complex +// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_NOT]], %[[B_ADDR]] : !cir.complex, !cir.ptr> + +// CIR-AFTER: %[[A_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["a"] +// CIR-AFTER: %[[B_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["b", init] +// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr>, !cir.complex +// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex -> !cir.float +// CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : !cir.complex -> !cir.float +// CIR-AFTER: %[[IMAG_MINUS:.*]] = cir.unary(minus, %[[IMAG]]) : !cir.float, !cir.float +// CIR-AFTER: %[[RESULT_VAL:.*]] = cir.complex.create %[[REAL]], %[[IMAG_MINUS]] : !cir.float -> !cir.complex +// CIR-AFTER: cir.store{{.*}} %[[RESULT_VAL]], %[[B_ADDR]] : !cir.complex, !cir.ptr> + +// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[B_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[TMP:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4 +// LLVM: %[[REAL:.*]] = extractvalue { float, float } %[[TMP]], 0 +// LLVM: %[[IMAG:.*]] = extractvalue { float, float } %[[TMP]], 1 +// LLVM: %[[IMAG_MINUS:.*]] = fneg float %[[IMAG]] +// LLVM: %[[RESULT_TMP:.*]] = insertvalue { float, float } {{.*}}, float %[[REAL]], 0 +// LLVM: %[[RESULT_VAL:.*]] = insertvalue { float, float } %[[RESULT_TMP]], float %[[IMAG_MINUS]], 1 +// LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[B_ADDR]], align 4 + +// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG: %[[B_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4 +// OGCG: %[[A_IMAG_MINUS:.*]] = fneg float %[[A_IMAG]] +// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 0 +// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 1 +// OGCG: store float %[[A_REAL]], ptr %[[RESULT_REAL_PTR]], align 4 +// OGCG: store float %[[A_IMAG_MINUS]], ptr %[[RESULT_IMAG_PTR]], align 4 + +void foo3() { + float _Complex a; + float _Complex b = a++; +} + +// CIR-BEFORE: %[[A_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["a"] +// CIR-BEFORE: %[[B_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["b", init] +// CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr>, !cir.complex +// CIR-BEFORE: %[[COMPLEX_INC:.*]] = cir.unary(inc, %[[TMP]]) : !cir.complex, !cir.complex +// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_INC]], %[[A_ADDR]] : !cir.complex, !cir.ptr> +// CIR-BEFORE: cir.store{{.*}} %[[TMP]], %[[B_ADDR]] : !cir.complex, !cir.ptr> + +// CIR-AFTER: %[[A_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["a"] +// CIR-AFTER: %[[B_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["b", init] +// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr>, !cir.complex +// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex -> !cir.float +// CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : !cir.complex -> !cir.float +// CIR-AFTER: %[[REAL_INC:.*]] = cir.unary(inc, %[[REAL]]) : !cir.float, !cir.float +// CIR-AFTER: %[[NEW_COMPLEX:.*]] = cir.complex.create %[[REAL_INC]], %[[IMAG]] : !cir.float -> !cir.complex +// CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[A_ADDR]] : !cir.complex, !cir.ptr> +// CIR-AFTER: cir.store{{.*}} %[[TMP]], %[[B_ADDR]] : !cir.complex, !cir.ptr> + +// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[B_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[TMP:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4 +// LLVM: %[[REAL:.*]] = extractvalue { float, float } %[[TMP]], 0 +// LLVM: %[[IMAG:.*]] = extractvalue { float, float } %[[TMP]], 1 +// LLVM: %[[REAL_INC:.*]] = fadd float 1.000000e+00, %[[REAL]] +// LLVM: %[[RESULT_TMP:.*]] = insertvalue { float, float } {{.*}}, float %[[REAL_INC]], 0 +// LLVM: %[[RESULT_VAL:.*]] = insertvalue { float, float } %[[RESULT_TMP]], float %[[IMAG]], 1 +// LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[A_ADDR]], align 4 +// LLVM: store { float, float } %[[TMP]], ptr %[[B_ADDR]], align 4 + +// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG: %[[B_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4 +// OGCG: %[[A_REAL_INC:.*]] = fadd float %[[A_REAL]], 1.000000e+00 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: store float %[[A_REAL_INC]], ptr %[[A_REAL_PTR]], align 4 +// OGCG: store float %[[A_IMAG]], ptr %[[A_IMAG_PTR]], align 4 +// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 0 +// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 1 +// OGCG: store float %[[A_REAL]], ptr %[[RESULT_REAL_PTR]], align 4 +// OGCG: store float %[[A_IMAG]], ptr %[[RESULT_IMAG_PTR]], align 4 + +void foo4() { + float _Complex a; + float _Complex b = ++a; +} + +// CIR-BEFORE: %[[A_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["a"] +// CIR-BEFORE: %[[B_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["b", init] +// CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr>, !cir.complex +// CIR-BEFORE: %[[COMPLEX_INC:.*]] = cir.unary(inc, %[[TMP]]) : !cir.complex, !cir.complex +// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_INC]], %[[A_ADDR]] : !cir.complex, !cir.ptr> +// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_INC]], %[[B_ADDR]] : !cir.complex, !cir.ptr> + +// CIR-AFTER: %[[A_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["a"] +// CIR-AFTER: %[[B_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["b", init] +// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr>, !cir.complex +// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex -> !cir.float +// CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : !cir.complex -> !cir.float +// CIR-AFTER: %[[REAL_INC:.*]] = cir.unary(inc, %[[REAL]]) : !cir.float, !cir.float +// CIR-AFTER: %[[NEW_COMPLEX:.*]] = cir.complex.create %[[REAL_INC]], %[[IMAG]] : !cir.float -> !cir.complex +// CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[A_ADDR]] : !cir.complex, !cir.ptr> +// CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[B_ADDR]] : !cir.complex, !cir.ptr> + +// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[B_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[TMP:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4 +// LLVM: %[[REAL:.*]] = extractvalue { float, float } %[[TMP]], 0 +// LLVM: %[[IMAG:.*]] = extractvalue { float, float } %[[TMP]], 1 +// LLVM: %[[REAL_INC:.*]] = fadd float 1.000000e+00, %[[REAL]] +// LLVM: %[[RESULT_TMP:.*]] = insertvalue { float, float } {{.*}}, float %[[REAL_INC]], 0 +// LLVM: %[[RESULT_VAL:.*]] = insertvalue { float, float } %[[RESULT_TMP]], float %[[IMAG]], 1 +// LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[A_ADDR]], align 4 +// LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[B_ADDR]], align 4 + +// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG: %[[B_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4 +// OGCG: %[[A_REAL_INC:.*]] = fadd float %[[A_REAL]], 1.000000e+00 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: store float %[[A_REAL_INC]], ptr %[[A_REAL_PTR]], align 4 +// OGCG: store float %[[A_IMAG]], ptr %[[A_IMAG_PTR]], align 4 +// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 0 +// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 1 +// OGCG: store float %[[A_REAL_INC]], ptr %[[RESULT_REAL_PTR]], align 4 +// OGCG: store float %[[A_IMAG]], ptr %[[RESULT_IMAG_PTR]], align 4 + +void foo5() { + float _Complex a; + float _Complex b = a--; +} + +// CIR-BEFORE: %[[A_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["a"] +// CIR-BEFORE: %[[B_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["b", init] +// CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr>, !cir.complex +// CIR-BEFORE: %[[COMPLEX_DEC:.*]] = cir.unary(dec, %[[TMP]]) : !cir.complex, !cir.complex +// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_DEC]], %[[A_ADDR]] : !cir.complex, !cir.ptr> +// CIR-BEFORE: cir.store{{.*}} %[[TMP]], %[[B_ADDR]] : !cir.complex, !cir.ptr> + +// CIR-AFTER: %[[A_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["a"] +// CIR-AFTER: %[[B_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["b", init] +// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr>, !cir.complex +// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex -> !cir.float +// CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : !cir.complex -> !cir.float +// CIR-AFTER: %[[REAL_DEC:.*]] = cir.unary(dec, %[[REAL]]) : !cir.float, !cir.float +// CIR-AFTER: %[[NEW_COMPLEX:.*]] = cir.complex.create %[[REAL_DEC]], %[[IMAG]] : !cir.float -> !cir.complex +// CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[A_ADDR]] : !cir.complex, !cir.ptr> +// CIR-AFTER: cir.store{{.*}} %[[TMP]], %[[B_ADDR]] : !cir.complex, !cir.ptr> + +// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[B_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[TMP:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4 +// LLVM: %[[REAL:.*]] = extractvalue { float, float } %[[TMP]], 0 +// LLVM: %[[IMAG:.*]] = extractvalue { float, float } %[[TMP]], 1 +// LLVM: %[[REAL_DEC:.*]] = fadd float -1.000000e+00, %[[REAL]] +// LLVM: %[[RESULT_TMP:.*]] = insertvalue { float, float } {{.*}}, float %[[REAL_DEC]], 0 +// LLVM: %[[RESULT_VAL:.*]] = insertvalue { float, float } %[[RESULT_TMP]], float %[[IMAG]], 1 +// LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[A_ADDR]], align 4 +// LLVM: store { float, float } %[[TMP]], ptr %[[B_ADDR]], align 4 + +// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG: %[[B_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4 +// OGCG: %[[A_REAL_DEC:.*]] = fadd float %[[A_REAL]], -1.000000e+00 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: store float %[[A_REAL_DEC]], ptr %[[A_REAL_PTR]], align 4 +// OGCG: store float %[[A_IMAG]], ptr %[[A_IMAG_PTR]], align 4 +// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 0 +// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 1 +// OGCG: store float %[[A_REAL]], ptr %[[RESULT_REAL_PTR]], align 4 +// OGCG: store float %[[A_IMAG]], ptr %[[RESULT_IMAG_PTR]], align 4 + +void foo6() { + float _Complex a; + float _Complex b = --a; +} + +// CIR-BEFORE: %[[A_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["a"] +// CIR-BEFORE: %[[B_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["b", init] +// CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr>, !cir.complex +// CIR-BEFORE: %[[COMPLEX_DEC:.*]] = cir.unary(dec, %[[TMP]]) : !cir.complex, !cir.complex +// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_DEC]], %[[A_ADDR]] : !cir.complex, !cir.ptr> +// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_DEC]], %[[B_ADDR]] : !cir.complex, !cir.ptr> + +// CIR-AFTER: %[[A_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["a"] +// CIR-AFTER: %[[B_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["b", init] +// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr>, !cir.complex +// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex -> !cir.float +// CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : !cir.complex -> !cir.float +// CIR-AFTER: %[[REAL_DEC:.*]] = cir.unary(dec, %[[REAL]]) : !cir.float, !cir.float +// CIR-AFTER: %[[NEW_COMPLEX:.*]] = cir.complex.create %[[REAL_DEC]], %[[IMAG]] : !cir.float -> !cir.complex +// CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[A_ADDR]] : !cir.complex, !cir.ptr> +// CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[B_ADDR]] : !cir.complex, !cir.ptr> + +// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[B_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[TMP:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4 +// LLVM: %[[REAL:.*]] = extractvalue { float, float } %[[TMP]], 0 +// LLVM: %[[IMAG:.*]] = extractvalue { float, float } %[[TMP]], 1 +// LLVM: %[[REAL_DEC:.*]] = fadd float -1.000000e+00, %[[REAL]] +// LLVM: %[[RESULT_TMP:.*]] = insertvalue { float, float } {{.*}}, float %[[REAL_DEC]], 0 +// LLVM: %[[RESULT_VAL:.*]] = insertvalue { float, float } %[[RESULT_TMP]], float %[[IMAG]], 1 +// LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[A_ADDR]], align 4 +// LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[B_ADDR]], align 4 + +// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG: %[[B_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4 +// OGCG: %[[A_REAL_DEC:.*]] = fadd float %[[A_REAL]], -1.000000e+00 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: store float %[[A_REAL_DEC]], ptr %[[A_REAL_PTR]], align 4 +// OGCG: store float %[[A_IMAG]], ptr %[[A_IMAG_PTR]], align 4 +// OGCG: %[[RESULT_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 0 +// OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 1 +// OGCG: store float %[[A_REAL_DEC]], ptr %[[RESULT_REAL_PTR]], align 4 +// OGCG: store float %[[A_IMAG]], ptr %[[RESULT_IMAG_PTR]], align 4 diff --git a/clang/test/CIR/CodeGen/compound_literal.cpp b/clang/test/CIR/CodeGen/compound_literal.cpp new file mode 100644 index 0000000000000..a92af95c62a1b --- /dev/null +++ b/clang/test/CIR/CodeGen/compound_literal.cpp @@ -0,0 +1,99 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG + +int foo() { + int e = (int){1}; + return e; +} + +// CIR: %[[RET:.*]] = cir.alloca !s32i, !cir.ptr, ["__retval"] +// CIR: %[[INIT:.*]] = cir.alloca !s32i, !cir.ptr, ["e", init] +// CIR: %[[COMPOUND:.*]] = cir.alloca !s32i, !cir.ptr, [".compoundliteral", init] +// CIR: %[[VALUE:.*]] = cir.const #cir.int<1> : !s32i +// CIR: cir.store{{.*}} %[[VALUE]], %[[COMPOUND]] : !s32i, !cir.ptr +// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[COMPOUND]] : !cir.ptr, !s32i +// CIR: cir.store{{.*}} %[[TMP]], %[[INIT]] : !s32i, !cir.ptr +// CIR: %[[TMP_2:.*]] = cir.load{{.*}} %[[INIT]] : !cir.ptr, !s32i +// CIR: cir.store %[[TMP_2]], %[[RET]] : !s32i, !cir.ptr +// CIR: %[[TMP_3:.*]] = cir.load %[[RET]] : !cir.ptr, !s32i +// CIR: cir.return %[[TMP_3]] : !s32i + +// LLVM: %[[RET:.*]] = alloca i32, i64 1, align 4 +// LLVM: %[[INIT:.*]] = alloca i32, i64 1, align 4 +// LLVM: %[[COMPOUND:.*]] = alloca i32, i64 1, align 4 +// LLVM: store i32 1, ptr %[[COMPOUND]], align 4 +// LLVM: %[[TMP:.*]] = load i32, ptr %[[COMPOUND]], align 4 +// LLVM: store i32 %[[TMP]], ptr %[[INIT]], align 4 +// LLVM: %[[TMP_2:.*]] = load i32, ptr %[[INIT]], align 4 +// LLVM: store i32 %[[TMP_2]], ptr %[[RET]], align 4 +// LLVM: %[[TMP_3:.*]] = load i32, ptr %[[RET]], align 4 +// LLVM: ret i32 %[[TMP_3]] + +// OGCG: %[[INIT:.*]] = alloca i32, align 4 +// OGCG: %[[COMPOUND:.*]] = alloca i32, align 4 +// OGCG: store i32 1, ptr %[[COMPOUND]], align 4 +// OGCG: %[[TMP:.*]] = load i32, ptr %[[COMPOUND]], align 4 +// OGCG: store i32 %[[TMP]], ptr %[[INIT]], align 4 +// OGCG: %[[TMP_2:.*]] = load i32, ptr %[[INIT]], align 4 +// OGCG: ret i32 %[[TMP_2]] + +void foo2() { + int _Complex a = (int _Complex) { 1, 2}; +} + +// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, ["a", init] +// CIR: %[[CL_ADDR:.*]] = cir.alloca !cir.complex, !cir.ptr>, [".compoundliteral"] +// CIR: %[[COMPLEX:.*]] = cir.const #cir.const_complex<#cir.int<1> : !s32i, #cir.int<2> : !s32i> : !cir.complex +// CIR: cir.store{{.*}} %[[COMPLEX]], %[[CL_ADDR]] : !cir.complex, !cir.ptr> +// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[CL_ADDR]] : !cir.ptr>, !cir.complex +// CIR: cir.store{{.*}} %[[TMP]], %[[A_ADDR]] : !cir.complex, !cir.ptr> + +// LLVM: %[[A_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4 +// LLVM: %[[CL_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4 +// LLVM: store { i32, i32 } { i32 1, i32 2 }, ptr %[[CL_ADDR]], align 4 +// LLVM: %[[TMP:.*]] = load { i32, i32 }, ptr %[[CL_ADDR]], align 4 +// LLVM: store { i32, i32 } %[[TMP]], ptr %[[A_ADDR]], align 4 + +// OGCG: %[[A_ADDR:.*]] = alloca { i32, i32 }, align 4 +// OGCG: %[[CL_ADDR:.*]] = alloca { i32, i32 }, align 4 +// OGCG: %[[CL_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[CL_ADDR]], i32 0, i32 0 +// OGCG: %[[CL_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[CL_ADDR]], i32 0, i32 1 +// OGCG: store i32 1, ptr %[[CL_REAL_PTR]], align 4 +// OGCG: store i32 2, ptr %[[CL_IMAG_PTR]], align 4 +// OGCG: %[[CL_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[CL_ADDR]], i32 0, i32 0 +// OGCG: %[[CL_REAL:.*]] = load i32, ptr %[[CL_REAL_PTR]], align 4 +// OGCG: %[[CL_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[CL_ADDR]], i32 0, i32 1 +// OGCG: %[[CL_IMAG:.*]] = load i32, ptr %[[CL_IMAG_PTR]], align 4 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: store i32 %[[CL_REAL]], ptr %[[A_REAL_PTR]], align 4 +// OGCG: store i32 %[[CL_IMAG]], ptr %[[A_IMAG_PTR]], align 4 + +void foo3() { + typedef int vi4 __attribute__((vector_size(16))); + auto a = (vi4){10, 20, 30, 40}; +} + +// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr>, ["a", init] +// CIR: %[[CL_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr>, [".compoundliteral", init] +// CIR: %[[VEC:.*]] = cir.const #cir.const_vector<[#cir.int<10> : !s32i, #cir.int<20> : !s32i, #cir.int<30> : !s32i, #cir.int<40> : !s32i]> : !cir.vector<4 x !s32i> +// CIR: cir.store{{.*}} %[[VEC]], %[[CL_ADDR]] : !cir.vector<4 x !s32i>, !cir.ptr> +// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[CL_ADDR]] : !cir.ptr>, !cir.vector<4 x !s32i> +// CIR: cir.store{{.*}} %[[TMP]], %[[A_ADDR]] : !cir.vector<4 x !s32i>, !cir.ptr> + +// LLVM: %[[A_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16 +// LLVM: %[[CL_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16 +// LLVM: store <4 x i32> , ptr %[[CL_ADDR]], align 16 +// LLVM: %[[TMP:.*]] = load <4 x i32>, ptr %[[CL_ADDR]], align 16 +// LLVM: store <4 x i32> %[[TMP]], ptr %[[A_ADDR]], align 16 + +// OGCG: %[[A_ADDR:.*]] = alloca <4 x i32>, align 16 +// OGCG: %[[CL_ADDR:.*]] = alloca <4 x i32>, align 16 +// OGCG: store <4 x i32> , ptr %[[CL_ADDR]], align 16 +// OGCG: %[[TMP:.*]] = load <4 x i32>, ptr %[[CL_ADDR]], align 16 +// OGCG: store <4 x i32> %[[TMP]], ptr %[[A_ADDR]], align 16 + diff --git a/clang/test/CIR/CodeGen/destructors.cpp b/clang/test/CIR/CodeGen/destructors.cpp index d8f9f23ae191c..de7718f0998fc 100644 --- a/clang/test/CIR/CodeGen/destructors.cpp +++ b/clang/test/CIR/CodeGen/destructors.cpp @@ -31,11 +31,11 @@ out_of_line_destructor::~out_of_line_destructor() { // OGCG: ret void // CIR: cir.func dso_local @_ZN22out_of_line_destructorD1Ev(%{{.+}}: !cir.ptr -// CIR: cir.call @_Z13some_functionv() nothrow : () -> () +// CIR: cir.call @_ZN22out_of_line_destructorD2Ev(%{{.*}}) nothrow : (!cir.ptr) // CIR: cir.return // LLVM: define dso_local void @_ZN22out_of_line_destructorD1Ev(ptr %{{.+}}) -// LLVM: call void @_Z13some_functionv() +// LLVM: call void @_ZN22out_of_line_destructorD2Ev // LLVM: ret void // OGCG: define dso_local void @_ZN22out_of_line_destructorD1Ev(ptr {{.*}}%{{.+}}) diff --git a/clang/test/CXX/drs/cwg14xx.cpp b/clang/test/CXX/drs/cwg14xx.cpp index 17d5c2fc2e210..047df171afffa 100644 --- a/clang/test/CXX/drs/cwg14xx.cpp +++ b/clang/test/CXX/drs/cwg14xx.cpp @@ -6,6 +6,14 @@ // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++98 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-17,since-cxx11, -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx14-17,cxx11-17,since-cxx11,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx14-17,cxx11-17,since-cxx11,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter + namespace cwg1413 { // cwg1413: 12 template struct Check { typedef int type; @@ -107,6 +115,8 @@ void f() { constexpr int p = &*a; // since-cxx11-error@-1 {{cannot initialize a variable of type 'const int' with an rvalue of type 'A *'}} constexpr A *p2 = &*a; + // since-cxx11-error@-1 {{constexpr variable 'p2' must be initialized by a constant expression}} + // since-cxx11-note@-2 {{dereferencing a null pointer}} } struct A { diff --git a/clang/test/CXX/drs/cwg2xx.cpp b/clang/test/CXX/drs/cwg2xx.cpp index a53a8d1ed64a8..556407afa2641 100644 --- a/clang/test/CXX/drs/cwg2xx.cpp +++ b/clang/test/CXX/drs/cwg2xx.cpp @@ -1429,7 +1429,7 @@ namespace cwg299 { // cwg299: 2.8 c++11 // cxx98-11-error@#cwg299-q {{ambiguous conversion of array size expression of type 'T' to an integral or enumeration type}} // cxx98-11-note@#cwg299-int {{conversion to integral type 'int' declared here}} // cxx98-11-note@#cwg299-ushort {{conversion to integral type 'unsigned short' declared here}} - // since-cxx14-error-re@#cwg299-q {{{{conversion from 'T' to 'unsigned (long long|long|int)' is ambiguous}}}} + // since-cxx14-error-re@#cwg299-q {{conversion from 'T' to '__size_t' (aka 'unsigned {{long long|long|int}}') is ambiguous}} // since-cxx14-note@#cwg299-int {{candidate function}} // since-cxx14-note@#cwg299-ushort {{candidate function}} } // namespace cwg299 diff --git a/clang/test/CXX/drs/cwg8xx.cpp b/clang/test/CXX/drs/cwg8xx.cpp index ecb9113ccfe66..7395f04c8e399 100644 --- a/clang/test/CXX/drs/cwg8xx.cpp +++ b/clang/test/CXX/drs/cwg8xx.cpp @@ -9,10 +9,10 @@ namespace cwg820 { // cwg820: 2.7 export template struct B {}; // cxx98-17-warning@-1 {{exported templates are unsupported}} -// since-cxx20-error@-2 {{export declaration can only be used within a module purview}} +// since-cxx20-error@-2 {{export declaration can only be used within a module interface}} export template void f() {} // cxx98-17-warning@-1 {{exported templates are unsupported}} -// since-cxx20-error@-2 {{export declaration can only be used within a module purview}} +// since-cxx20-error@-2 {{export declaration can only be used within a module interface}} } // namespace cwg820 namespace cwg873 { // cwg873: 3.0 diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp index c6c3381be5523..910c8635f7353 100644 --- a/clang/test/CXX/expr/expr.const/p2-0x.cpp +++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp @@ -199,15 +199,15 @@ namespace UndefinedBehavior { constexpr A *na = nullptr; constexpr B *nb = nullptr; - constexpr A &ra = *nb; // expected-error {{constant expression}} expected-note {{cannot access base class of null pointer}} - constexpr B &rb = (B&)*na; // expected-error {{constant expression}} expected-note {{cannot access derived class of null pointer}} + constexpr A &ra = *nb; // expected-error {{constant expression}} expected-note {{dereferencing a null pointer}} + constexpr B &rb = (B&)*na; // expected-error {{constant expression}} expected-note {{dereferencing a null pointer}} static_assert((A*)nb == 0, ""); static_assert((B*)na == 0, ""); constexpr const int &nf = nb->n; // expected-error {{constant expression}} expected-note {{cannot access field of null pointer}} constexpr const int &mf = nb->m; // expected-error {{constant expression}} expected-note {{cannot access field of null pointer}} constexpr const int *np1 = (int*)nullptr + 0; // ok - constexpr const int *np2 = &(*(int(*)[4])nullptr)[0]; // ok - constexpr const int *np3 = &(*(int(*)[4])nullptr)[2]; // expected-error {{constant expression}} expected-note {{cannot perform pointer arithmetic on null pointer}} + constexpr const int *np2 = &(*(int(*)[4])nullptr)[0]; // expected-error {{constant expression}} expected-note {{dereferencing a null pointer}} + constexpr const int *np3 = &(*(int(*)[4])nullptr)[2]; // expected-error {{constant expression}} expected-note {{dereferencing a null pointer}} struct C { constexpr int f() const { return 0; } @@ -485,7 +485,7 @@ namespace std { namespace TypeId { struct S { virtual void f(); }; constexpr S *p = 0; - constexpr const std::type_info &ti1 = typeid(*p); // expected-error {{must be initialized by a constant expression}} cxx11-note {{typeid applied to expression of polymorphic type 'S'}} cxx20-note {{dereferenced null pointer}} + constexpr const std::type_info &ti1 = typeid(*p); // expected-error {{must be initialized by a constant expression}} cxx11-note {{typeid applied to expression of polymorphic type 'S'}} cxx20-note {{dereferencing a null pointer}} struct T {} t; constexpr const std::type_info &ti2 = typeid(t); diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p2.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p2.cpp index 6942b68690c5d..d439f304b5101 100644 --- a/clang/test/CXX/lex/lex.literal/lex.ext/p2.cpp +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p2.cpp @@ -5,11 +5,11 @@ typedef decltype(sizeof(int)) size_t; // FIXME: These diagnostics should say 'size_t' instead of 'unsigned long' int a = 123_x; // expected-error {{no matching literal operator for call to 'operator""_x' with argument of type 'unsigned long long' or 'const char *', and no matching literal operator template}} int b = 4.2_x; // expected-error {{no matching literal operator for call to 'operator""_x' with argument of type 'long double' or 'const char *', and no matching literal operator template}} -int c = "foo"_x; // expected-error {{no matching literal operator for call to 'operator""_x' with arguments of types 'const char *' and 'unsigned}} -int d = L"foo"_x; // expected-error {{no matching literal operator for call to 'operator""_x' with arguments of types 'const wchar_t *' and 'unsigned}} -int e = u8"foo"_x; // expected-error {{no matching literal operator for call to 'operator""_x' with arguments of types 'const char *' and 'unsigned}} -int f = u"foo"_x; // expected-error {{no matching literal operator for call to 'operator""_x' with arguments of types 'const char16_t *' and 'unsigned}} -int g = U"foo"_x; // expected-error {{no matching literal operator for call to 'operator""_x' with arguments of types 'const char32_t *' and 'unsigned}} +int c = "foo"_x; // expected-error {{no matching literal operator for call to 'operator""_x' with arguments of types 'const char *' and '__size_t' (aka 'unsigned}} +int d = L"foo"_x; // expected-error {{no matching literal operator for call to 'operator""_x' with arguments of types 'const wchar_t *' and '__size_t' (aka 'unsigned}} +int e = u8"foo"_x; // expected-error {{no matching literal operator for call to 'operator""_x' with arguments of types 'const char *' and '__size_t' (aka 'unsigned}} +int f = u"foo"_x; // expected-error {{no matching literal operator for call to 'operator""_x' with arguments of types 'const char16_t *' and '__size_t' (aka 'unsigned}} +int g = U"foo"_x; // expected-error {{no matching literal operator for call to 'operator""_x' with arguments of types 'const char32_t *' and '__size_t' (aka 'unsigned}} int h = 'y'_x; // expected-error {{no matching literal operator for call to 'operator""_x' with argument of type 'char'}} int i = L'y'_x; // expected-error {{no matching literal operator for call to 'operator""_x' with argument of type 'wchar_t'}} int j = u'y'_x; // expected-error {{no matching literal operator for call to 'operator""_x' with argument of type 'char16_t'}} diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p5.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p5.cpp index afadba282e626..463d7854867a2 100644 --- a/clang/test/CXX/lex/lex.literal/lex.ext/p5.cpp +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p5.cpp @@ -13,7 +13,7 @@ float &operator ""_x1 (const char8_t *, size_t); using char8 = double; #endif char8 &i2 = u8"foo"_x1; -double &i3 = L"foo"_x1; // expected-error {{no matching literal operator for call to 'operator""_x1' with arguments of types 'const wchar_t *' and 'unsigned long'}} +double &i3 = L"foo"_x1; // expected-error {{no matching literal operator for call to 'operator""_x1' with arguments of types 'const wchar_t *' and '__size_t' (aka 'unsigned long')}} char &operator ""_x1(const wchar_t *, size_t); char &i4 = L"foo"_x1; // ok @@ -46,8 +46,8 @@ template float &operator""_s(); void no_fallback() { "hello"_s; // FIXME: It'd be useful to explain what candidates were found and why they didn't work. - "xyzzy"_s; // expected-error {{no matching literal operator for call to 'operator""_s' with arguments of types 'const char *' and 'unsigned long', and no matching literal operator template}} - "yello"_s; // expected-error {{no matching literal operator for call to 'operator""_s' with arguments of types 'const char *' and 'unsigned long', and no matching literal operator template}} + "xyzzy"_s; // expected-error {{no matching literal operator for call to 'operator""_s' with arguments of types 'const char *' and '__size_t' (aka 'unsigned long'), and no matching literal operator template}} + "yello"_s; // expected-error {{no matching literal operator for call to 'operator""_s' with arguments of types 'const char *' and '__size_t' (aka 'unsigned long'), and no matching literal operator template}} } double &operator""_s(const char*, size_t); diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p7.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p7.cpp index d571fcb8697eb..17d9c83055a1c 100644 --- a/clang/test/CXX/lex/lex.literal/lex.ext/p7.cpp +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p7.cpp @@ -17,7 +17,7 @@ int main() { auto v1 = 1.2_w; // calls operator""_w(1.2L) auto v2 = u"one"_w; // calls operator""_w(u"one", 3) auto v3 = 12_w; // calls operator""_w("12") - "two"_w; // expected-error {{no matching literal operator for call to 'operator""_w' with arguments of types 'const char *' and 'unsigned long'}} + "two"_w; // expected-error {{no matching literal operator for call to 'operator""_w' with arguments of types 'const char *' and '__size_t' (aka 'unsigned long')}} same_type test1; same_type test2; diff --git a/clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.interface/p1.cppm b/clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.interface/p1.cppm index 2158d7fa84b86..ebc76ad16467d 100644 --- a/clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.interface/p1.cppm +++ b/clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.interface/p1.cppm @@ -9,7 +9,7 @@ //--- ExportDeclNotInModulePurview.cppm // expected-error@* {{missing 'export module' declaration in module interface unit}} -export int b; // expected-error {{export declaration can only be used within a module purview}} +export int b; // expected-error {{export declaration can only be used within a module interface}} //--- A.cppm // expected-no-diagnostics @@ -18,7 +18,7 @@ export int a; //--- AddExport.cppm module A; // #module-decl -export int b; // expected-error {{export declaration can only be used within a module purview}} +export int b; // expected-error {{export declaration can only be used within a module interface}} // expected-note@#module-decl {{add 'export' here}} //--- AddExport2.cppm diff --git a/clang/test/CXX/module/module.interface/p1.cpp b/clang/test/CXX/module/module.interface/p1.cpp index c3bfca930f5cc..1754d9ea14618 100644 --- a/clang/test/CXX/module/module.interface/p1.cpp +++ b/clang/test/CXX/module/module.interface/p1.cpp @@ -7,7 +7,7 @@ //--- errors.cpp module; -export int a; // expected-error {{export declaration can only be used within a module purview}} +export int a; // expected-error {{export declaration can only be used within a module interface}} export module M; export int b; // #1 namespace N { @@ -37,8 +37,8 @@ namespace N { //--- impl.cpp module M; // #M -export int b2; // expected-error {{export declaration can only be used within a module purview}} +export int b2; // expected-error {{export declaration can only be used within a module interface}} namespace N { - export int c2; // expected-error {{export declaration can only be used within a module purview}} + export int c2; // expected-error {{export declaration can only be used within a module interface}} } // expected-note@#M 2+{{add 'export'}} diff --git a/clang/test/ClangScanDeps/modules-full-named-modules.cppm b/clang/test/ClangScanDeps/modules-full-named-modules.cppm index 5967a8705c09d..c69a215a62dc1 100644 --- a/clang/test/ClangScanDeps/modules-full-named-modules.cppm +++ b/clang/test/ClangScanDeps/modules-full-named-modules.cppm @@ -92,14 +92,7 @@ export void Hello(); // CHECK-NEXT: ] // CHECK: "command-line": [ // CHECK: "-o", -// CHECK-NEXT: "{{.*}}/M-{{.*}}.pcm" -// CHECK: ] -// CHECK: "input-file": "[[PREFIX]]/M.cppm" -// CHECK: }, -// CHECK-NEXT: { -// CHECK: "command-line": [ -// CHECK: "-o", -// CHECK-NEXT: "[[PREFIX]]/M.o" +// CHECK-NEXT: "{{.*}}/M.o" // CHECK: ] // CHECK: "input-file": "[[PREFIX]]/M.cppm" // CHECK: } @@ -160,18 +153,7 @@ void World() { // CHECK-NEXT: ] // CHECK: "command-line": [ // CHECK: "-o", -// CHECK-NEXT: "{{.*}}/impl_part-{{.*}}.pcm", -// CHECK: ] -// CHECK: "input-file": "[[PREFIX]]/impl_part.cppm" -// CHECK: }, -// CHECK-NEXT: { -// CHECK: "named-module": "M:impl_part" -// CHECK-NEXT: "named-module-deps": [ -// CHECK-NEXT: "M:interface_part" -// CHECK-NEXT: ] -// CHECK: "command-line": [ -// CHECK: "-o", -// CHECK-NEXT: "[[PREFIX]]/impl_part.o", +// CHECK-NEXT: "{{.*}}/impl_part.o", // CHECK: ] // CHECK: "input-file": "[[PREFIX]]/impl_part.cppm" // CHECK: } @@ -194,16 +176,7 @@ export void World(); // CHECK-NOT: "named-module-deps": [] // CHECK: "command-line": [ // CHECK: "-o", -// CHECK-NEXT: "{{.*}}/interface_part-{{.*}}.pcm", -// CHECK: ] -// CHECK: "input-file": "[[PREFIX]]/interface_part.cppm" -// CHECK: }, -// CHECK-NEXT: { -// CHECK: "named-module": "M:interface_part" -// CHECK-NOT: "named-module-deps": [] -// CHECK: "command-line": [ -// CHECK: "-o", -// CHECK-NEXT: "[[PREFIX]]/interface_part.o", +// CHECK-NEXT: "{{.*}}/interface_part.o", // CHECK: ] // CHECK: "input-file": "[[PREFIX]]/interface_part.cppm" // CHECK: } @@ -259,14 +232,7 @@ int main() { // CHECK-NEXT: ] // CHECK: "command-line": [ // CHECK: "-o", -// CHECK-NEXT: "{{.*}}/M-{{.*}}.pcm" -// CHECK: ] -// CHECK: "input-file": "[[PREFIX]]/M.cppm" -// CHECK: }, -// CHECK-NEXT: { -// CHECK: "command-line": [ -// CHECK: "-o", -// CHECK-NEXT: "[[PREFIX]]/M.o" +// CHECK-NEXT: "{{.*}}/M.o" // CHECK: ] // CHECK: "input-file": "[[PREFIX]]/M.cppm" // CHECK: }, @@ -292,18 +258,7 @@ int main() { // CHECK-NEXT: ] // CHECK: "command-line": [ // CHECK: "-o", -// CHECK-NEXT: "{{.*}}/impl_part-{{.*}}.pcm", -// CHECK: ] -// CHECK: "input-file": "[[PREFIX]]/impl_part.cppm" -// CHECK: }, -// CHECK-NEXT: { -// CHECK: "named-module": "M:impl_part" -// CHECK-NEXT: "named-module-deps": [ -// CHECK-NEXT: "M:interface_part" -// CHECK-NEXT: ] -// CHECK: "command-line": [ -// CHECK: "-o", -// CHECK-NEXT: "[[PREFIX]]/impl_part.o", +// CHECK-NEXT: "{{.*}}/impl_part.o", // CHECK: ] // CHECK: "input-file": "[[PREFIX]]/impl_part.cppm" // CHECK: } @@ -316,16 +271,7 @@ int main() { // CHECK-NOT: "named-module-deps": [] // CHECK: "command-line": [ // CHECK: "-o", -// CHECK-NEXT: "{{.*}}/interface_part-{{.*}}.pcm", -// CHECK: ] -// CHECK: "input-file": "[[PREFIX]]/interface_part.cppm" -// CHECK: }, -// CHECK-NEXT: { -// CHECK: "named-module": "M:interface_part" -// CHECK-NOT: "named-module-deps": [] -// CHECK: "command-line": [ -// CHECK: "-o", -// CHECK-NEXT: "[[PREFIX]]/interface_part.o", +// CHECK-NEXT: "{{.*}}/interface_part.o", // CHECK: ] // CHECK: "input-file": "[[PREFIX]]/interface_part.cppm" // CHECK: } diff --git a/clang/test/CodeGen/64bit-swiftcall.c b/clang/test/CodeGen/64bit-swiftcall.c index 7f8aa02d97ce1..448bca7acbca3 100644 --- a/clang/test/CodeGen/64bit-swiftcall.c +++ b/clang/test/CodeGen/64bit-swiftcall.c @@ -239,7 +239,7 @@ TEST(struct_big_1) // CHECK-LABEL: define {{.*}} void @return_struct_big_1(ptr dead_on_unwind noalias writable sret // Should not be byval. -// CHECK-LABEL: define {{.*}} void @take_struct_big_1(ptr{{( %.*)?}}) +// CHECK-LABEL: define {{.*}} void @take_struct_big_1(ptr dead_on_return{{( %.*)?}}) /*****************************************************************************/ /********************************* TYPE MERGING ******************************/ diff --git a/clang/test/CodeGen/AArch64/byval-temp.c b/clang/test/CodeGen/AArch64/byval-temp.c index 0ee0312b2362d..5033b6cf5ac03 100644 --- a/clang/test/CodeGen/AArch64/byval-temp.c +++ b/clang/test/CodeGen/AArch64/byval-temp.c @@ -30,10 +30,10 @@ void example(void) { // Then, memcpy `l` to the temporary stack space. // CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[byvaltemp]], ptr align 8 %[[l]], i64 64, i1 false) // Finally, call using a pointer to the temporary stack space. -// CHECK-O0-NEXT: call void @pass_large(ptr noundef %[[byvaltemp]]) +// CHECK-O0-NEXT: call void @pass_large(ptr dead_on_return noundef %[[byvaltemp]]) // Now, do the same for the second call, using the second temporary alloca. // CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[byvaltemp1]], ptr align 8 %[[l]], i64 64, i1 false) -// CHECK-O0-NEXT: call void @pass_large(ptr noundef %[[byvaltemp1]]) +// CHECK-O0-NEXT: call void @pass_large(ptr dead_on_return noundef %[[byvaltemp1]]) // CHECK-O0-NEXT: ret void // // At O3, we should have lifetime markers to help the optimizer re-use the temporary allocas. @@ -58,7 +58,7 @@ void example(void) { // Then, memcpy `l` to the temporary stack space. // CHECK-O3-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[byvaltemp]], ptr align 8 %[[l]], i64 64, i1 false) // Finally, call using a pointer to the temporary stack space. -// CHECK-O3-NEXT: call void @pass_large(ptr noundef %[[byvaltemp]]) +// CHECK-O3-NEXT: call void @pass_large(ptr dead_on_return noundef %[[byvaltemp]]) // // The lifetime of the temporary used to pass a pointer to the struct ends here. // CHECK-O3-NEXT: call void @llvm.lifetime.end.p0(i64 64, ptr %[[byvaltemp]]) @@ -66,7 +66,7 @@ void example(void) { // Now, do the same for the second call, using the second temporary alloca. // CHECK-O3-NEXT: call void @llvm.lifetime.start.p0(i64 64, ptr %[[byvaltemp1]]) // CHECK-O3-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[byvaltemp1]], ptr align 8 %[[l]], i64 64, i1 false) -// CHECK-O3-NEXT: call void @pass_large(ptr noundef %[[byvaltemp1]]) +// CHECK-O3-NEXT: call void @pass_large(ptr dead_on_return noundef %[[byvaltemp1]]) // CHECK-O3-NEXT: call void @llvm.lifetime.end.p0(i64 64, ptr %[[byvaltemp1]]) // // Mark the end of the lifetime of `l`. @@ -88,12 +88,12 @@ void example_BitInt(void) { // CHECK-O0-NEXT: [[LOADEDV:%.*]] = trunc i256 [[TMP0]] to i129 // CHECK-O0-NEXT: [[STOREDV:%.*]] = sext i129 [[LOADEDV]] to i256 // CHECK-O0-NEXT: store i256 [[STOREDV]], ptr [[INDIRECT_ARG_TEMP]], align 16 -// CHECK-O0-NEXT: call void @pass_large_BitInt(ptr noundef [[INDIRECT_ARG_TEMP]]) +// CHECK-O0-NEXT: call void @pass_large_BitInt(ptr dead_on_return noundef [[INDIRECT_ARG_TEMP]]) // CHECK-O0-NEXT: [[TMP1:%.*]] = load i256, ptr [[L]], align 16 // CHECK-O0-NEXT: [[LOADEDV1:%.*]] = trunc i256 [[TMP1]] to i129 // CHECK-O0-NEXT: [[STOREDV1:%.*]] = sext i129 [[LOADEDV1]] to i256 // CHECK-O0-NEXT: store i256 [[STOREDV1]], ptr [[INDIRECT_ARG_TEMP1]], align 16 -// CHECK-O0-NEXT: call void @pass_large_BitInt(ptr noundef [[INDIRECT_ARG_TEMP1]]) +// CHECK-O0-NEXT: call void @pass_large_BitInt(ptr dead_on_return noundef [[INDIRECT_ARG_TEMP1]]) // CHECK-O0-NEXT: ret void // // CHECK-O3-LABEL: define dso_local void @example_BitInt( @@ -108,13 +108,13 @@ void example_BitInt(void) { // CHECK-O3-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr [[INDIRECT_ARG_TEMP]]) // CHECK-O3-NEXT: [[STOREDV:%.*]] = sext i129 [[LOADEDV]] to i256 // CHECK-O3-NEXT: store i256 [[STOREDV]], ptr [[INDIRECT_ARG_TEMP]], align 16, !tbaa [[TBAA6]] -// CHECK-O3-NEXT: call void @pass_large_BitInt(ptr noundef [[INDIRECT_ARG_TEMP]]) +// CHECK-O3-NEXT: call void @pass_large_BitInt(ptr dead_on_return noundef [[INDIRECT_ARG_TEMP]]) // CHECK-O3-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr [[INDIRECT_ARG_TEMP]]) // CHECK-O3-NEXT: [[TMP1:%.*]] = load i256, ptr [[L]], align 16, !tbaa [[TBAA6]] // CHECK-O3-NEXT: [[LOADEDV1:%.*]] = trunc i256 [[TMP1]] to i129 // CHECK-O3-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr [[INDIRECT_ARG_TEMP1]]) // CHECK-O3-NEXT: [[STOREDV1:%.*]] = sext i129 [[LOADEDV1]] to i256 // CHECK-O3-NEXT: store i256 [[STOREDV1]], ptr [[INDIRECT_ARG_TEMP1]], align 16, !tbaa [[TBAA6]] -// CHECK-O3-NEXT: call void @pass_large_BitInt(ptr noundef [[INDIRECT_ARG_TEMP1]]) +// CHECK-O3-NEXT: call void @pass_large_BitInt(ptr dead_on_return noundef [[INDIRECT_ARG_TEMP1]]) // CHECK-O3-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr [[INDIRECT_ARG_TEMP1]]) // CHECK-O3-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr [[L]]) diff --git a/clang/test/CodeGen/AArch64/pure-scalable-args-empty-union.c b/clang/test/CodeGen/AArch64/pure-scalable-args-empty-union.c index 546910068c78a..804e14a2ea34b 100644 --- a/clang/test/CodeGen/AArch64/pure-scalable-args-empty-union.c +++ b/clang/test/CodeGen/AArch64/pure-scalable-args-empty-union.c @@ -19,7 +19,7 @@ void f0(S0 *p) { use0(*p); } // CHECK-C: declare void @use0(, , , ) -// CHECK-CXX: declare void @use0(ptr noundef) +// CHECK-CXX: declare void @use0(ptr dead_on_return noundef) #ifdef __cplusplus diff --git a/clang/test/CodeGen/AArch64/pure-scalable-args.c b/clang/test/CodeGen/AArch64/pure-scalable-args.c index fecd370d09be3..48988f7a1722b 100644 --- a/clang/test/CodeGen/AArch64/pure-scalable-args.c +++ b/clang/test/CodeGen/AArch64/pure-scalable-args.c @@ -92,7 +92,7 @@ void test_argpass_simple(PST *p) { // CHECK-AAPCS-NEXT: ret void // CHECK-AAPCS: declare void @argpass_simple_callee(, , , , , ) -// CHECK-DARWIN: declare void @argpass_simple_callee(ptr noundef) +// CHECK-DARWIN: declare void @argpass_simple_callee(ptr dead_on_return noundef) // Boundary case of using the last available Z-reg, PST expanded. // 0.0 -> d0-d3 @@ -107,7 +107,7 @@ void test_argpass_last_z(PST *p) { argpass_last_z_callee(.0, .0, .0, .0, *p); } // CHECK-AAPCS: declare void @argpass_last_z_callee(double noundef, double noundef, double noundef, double noundef, , , , , , ) -// CHECK-DARWIN: declare void @argpass_last_z_callee(double noundef, double noundef, double noundef, double noundef, ptr noundef) +// CHECK-DARWIN: declare void @argpass_last_z_callee(double noundef, double noundef, double noundef, double noundef, ptr dead_on_return noundef) // Like the above, but using a tuple type to occupy some registers. @@ -123,7 +123,7 @@ void test_argpass_last_z_tuple(PST *p, svfloat64x4_t x) { argpass_last_z_tuple_callee(x, *p); } // CHECK-AAPCS: declare void @argpass_last_z_tuple_callee(, , , , , , , , , ) -// CHECK-DARWIN: declare void @argpass_last_z_tuple_callee(, , , , ptr noundef) +// CHECK-DARWIN: declare void @argpass_last_z_tuple_callee(, , , , ptr dead_on_return noundef) // Boundary case of using the last available P-reg, PST expanded. @@ -139,7 +139,7 @@ void test_argpass_last_p(PST *p) { argpass_last_p_callee(svpfalse(), svpfalse_c(), *p); } // CHECK-AAPCS: declare void @argpass_last_p_callee(, target("aarch64.svcount"), , , , , , ) -// CHECK-DARWIN: declare void @argpass_last_p_callee(, target("aarch64.svcount"), ptr noundef) +// CHECK-DARWIN: declare void @argpass_last_p_callee(, target("aarch64.svcount"), ptr dead_on_return noundef) // Not enough Z-regs, push PST to memory and pass a pointer, Z-regs and @@ -157,7 +157,7 @@ void test_argpass_no_z(PST *p, double dummy, svmfloat8_t u, int8x16_t v, mfloat8 void argpass_no_z_callee(svmfloat8_t, int8x16_t, mfloat8x16_t, double, double, int, PST, int, double, svbool_t); argpass_no_z_callee(u, v, w, .0, .0, 1, *p, 2, 3.0, svptrue_b64()); } -// CHECK: declare void @argpass_no_z_callee(, <16 x i8> noundef, <16 x i8>, double noundef, double noundef, i32 noundef, ptr noundef, i32 noundef, double noundef, ) +// CHECK: declare void @argpass_no_z_callee(, <16 x i8> noundef, <16 x i8>, double noundef, double noundef, i32 noundef, ptr dead_on_return noundef, i32 noundef, double noundef, ) // Like the above, using a tuple to occupy some registers. @@ -173,7 +173,7 @@ void test_argpass_no_z_tuple_f64(PST *p, float dummy, svfloat64x4_t x) { double, svbool_t); argpass_no_z_tuple_f64_callee(x, .0, 1, *p, 2, 3.0, svptrue_b64()); } -// CHECK: declare void @argpass_no_z_tuple_f64_callee(, , , , double noundef, i32 noundef, ptr noundef, i32 noundef, double noundef, ) +// CHECK: declare void @argpass_no_z_tuple_f64_callee(, , , , double noundef, i32 noundef, ptr dead_on_return noundef, i32 noundef, double noundef, ) // Likewise, using a different tuple. @@ -189,7 +189,7 @@ void test_argpass_no_z_tuple_mfp8(PST *p, float dummy, svmfloat8x4_t x) { double, svbool_t); argpass_no_z_tuple_mfp8_callee(x, .0, 1, *p, 2, 3.0, svptrue_b64()); } -// CHECK: declare void @argpass_no_z_tuple_mfp8_callee(, , , , double noundef, i32 noundef, ptr noundef, i32 noundef, double noundef, ) +// CHECK: declare void @argpass_no_z_tuple_mfp8_callee(, , , , double noundef, i32 noundef, ptr dead_on_return noundef, i32 noundef, double noundef, ) // Not enough Z-regs (consumed by a HFA), PST passed indirectly @@ -204,8 +204,8 @@ void test_argpass_no_z_hfa(HFA *h, PST *p) { void argpass_no_z_hfa_callee(double, HFA, int, PST, int, svbool_t); argpass_no_z_hfa_callee(.0, *h, 1, *p, 2, svptrue_b64()); } -// CHECK-AAPCS: declare void @argpass_no_z_hfa_callee(double noundef, [4 x float] alignstack(8), i32 noundef, ptr noundef, i32 noundef, ) -// CHECK-DARWIN: declare void @argpass_no_z_hfa_callee(double noundef, [4 x float], i32 noundef, ptr noundef, i32 noundef, ) +// CHECK-AAPCS: declare void @argpass_no_z_hfa_callee(double noundef, [4 x float] alignstack(8), i32 noundef, ptr dead_on_return noundef, i32 noundef, ) +// CHECK-DARWIN: declare void @argpass_no_z_hfa_callee(double noundef, [4 x float], i32 noundef, ptr dead_on_return noundef, i32 noundef, ) // Not enough Z-regs (consumed by a HVA), PST passed indirectly // 0.0 -> d0 @@ -219,8 +219,8 @@ void test_argpass_no_z_hva(HVA *h, PST *p) { void argpass_no_z_hva_callee(double, HVA, int, PST, int, svbool_t); argpass_no_z_hva_callee(.0, *h, 1, *p, 2, svptrue_b64()); } -// CHECK-AAPCS: declare void @argpass_no_z_hva_callee(double noundef, [4 x <16 x i8>] alignstack(16), i32 noundef, ptr noundef, i32 noundef, ) -// CHECK-DARWIN: declare void @argpass_no_z_hva_callee(double noundef, [4 x <16 x i8>], i32 noundef, ptr noundef, i32 noundef, ) +// CHECK-AAPCS: declare void @argpass_no_z_hva_callee(double noundef, [4 x <16 x i8>] alignstack(16), i32 noundef, ptr dead_on_return noundef, i32 noundef, ) +// CHECK-DARWIN: declare void @argpass_no_z_hva_callee(double noundef, [4 x <16 x i8>], i32 noundef, ptr dead_on_return noundef, i32 noundef, ) // Not enough P-regs, PST passed indirectly, Z-regs and P-regs still available. // true -> p0-p2 @@ -233,7 +233,7 @@ void test_argpass_no_p(PST *p) { void argpass_no_p_callee(svbool_t, svbool_t, svbool_t, int, PST, int, double, svbool_t); argpass_no_p_callee(svptrue_b8(), svptrue_b16(), svptrue_b32(), 1, *p, 2, 3.0, svptrue_b64()); } -// CHECK: declare void @argpass_no_p_callee(, , , i32 noundef, ptr noundef, i32 noundef, double noundef, ) +// CHECK: declare void @argpass_no_p_callee(, , , i32 noundef, ptr dead_on_return noundef, i32 noundef, double noundef, ) // Like above, using a tuple to occupy some registers. @@ -250,7 +250,7 @@ void test_argpass_no_p_tuple(PST *p, svbool_t u, svboolx2_t v) { svbool_t); argpass_no_p_tuple_callee(v, u, 1, *p, 2, 3.0, svptrue_b64()); } -// CHECK: declare void @argpass_no_p_tuple_callee(, , , i32 noundef, ptr noundef, i32 noundef, double noundef, ) +// CHECK: declare void @argpass_no_p_tuple_callee(, , , i32 noundef, ptr dead_on_return noundef, i32 noundef, double noundef, ) // HFAs go back-to-back to memory, afterwards Z-regs not available, PST passed indirectly. @@ -263,8 +263,8 @@ void test_after_hfa(HFA *h, PST *p) { void after_hfa_callee(double, double, double, double, double, HFA, PST, HFA, svbool_t); after_hfa_callee(.0, .0, .0, .0, .0, *h, *p, *h, svpfalse()); } -// CHECK-AAPCS: declare void @after_hfa_callee(double noundef, double noundef, double noundef, double noundef, double noundef, [4 x float] alignstack(8), ptr noundef, [4 x float] alignstack(8), ) -// CHECK-DARWIN: declare void @after_hfa_callee(double noundef, double noundef, double noundef, double noundef, double noundef, [4 x float], ptr noundef, [4 x float], ) +// CHECK-AAPCS: declare void @after_hfa_callee(double noundef, double noundef, double noundef, double noundef, double noundef, [4 x float] alignstack(8), ptr dead_on_return noundef, [4 x float] alignstack(8), ) +// CHECK-DARWIN: declare void @after_hfa_callee(double noundef, double noundef, double noundef, double noundef, double noundef, [4 x float], ptr dead_on_return noundef, [4 x float], ) // Small PST, not enough registers, passed indirectly, unlike other small // aggregates. @@ -277,7 +277,7 @@ void test_small_pst(SmallPST *p, SmallAgg *s) { void small_pst_callee(SmallAgg, double, double, double, double, double, double, double, double, double, SmallPST, double); small_pst_callee(*s, .0, .0, .0, .0, .0, .0, .0, .0, 1.0, *p, 2.0); } -// CHECK-AAPCS: declare void @small_pst_callee([2 x i64], double noundef, double noundef, double noundef, double noundef, double noundef, double noundef, double noundef, double noundef, double noundef, ptr noundef, double noundef) +// CHECK-AAPCS: declare void @small_pst_callee([2 x i64], double noundef, double noundef, double noundef, double noundef, double noundef, double noundef, double noundef, double noundef, double noundef, ptr dead_on_return noundef, double noundef) // CHECK-DARWIN: declare void @small_pst_callee([2 x i64], double noundef, double noundef, double noundef, double noundef, double noundef, double noundef, double noundef, double noundef, double noundef, i128, double noundef) @@ -326,12 +326,12 @@ void test_pass_variadic(PST *p, PST *q) { pass_variadic_callee(*p, *q); } // CHECK-AAPCS: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 16 dereferenceable(96) %byval-temp, ptr noundef nonnull align 16 dereferenceable(96) %q, i64 96, i1 false) -// CHECK-AAPCS: call void (, , , , , , ...) @pass_variadic_callee( %1, %cast.scalable1, %cast.scalable2, %cast.scalable3, %cast.scalable4, %12, ptr noundef nonnull %byval-temp) +// CHECK-AAPCS: call void (, , , , , , ...) @pass_variadic_callee( %1, %cast.scalable1, %cast.scalable2, %cast.scalable3, %cast.scalable4, %12, ptr dead_on_return noundef nonnull %byval-temp) // CHECK-DARWIN: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 16 dereferenceable(96) %byval-temp, ptr noundef nonnull align 16 dereferenceable(96) %p, i64 96, i1 false) // CHECK-DARWIN: call void @llvm.lifetime.start.p0(i64 96, ptr nonnull %byval-temp1) // CHECK-DARWIN: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 16 dereferenceable(96) %byval-temp1, ptr noundef nonnull align 16 dereferenceable(96) %q, i64 96, i1 false) -// CHECK-DARWIN: call void (ptr, ...) @pass_variadic_callee(ptr noundef nonnull %byval-temp, ptr noundef nonnull %byval-temp1) +// CHECK-DARWIN: call void (ptr, ...) @pass_variadic_callee(ptr dead_on_return noundef nonnull %byval-temp, ptr dead_on_return noundef nonnull %byval-temp1) // Test passing a small PST, still passed indirectly, despite being <= 128 bits @@ -340,7 +340,7 @@ void test_small_pst_variadic(SmallPST *p) { small_pst_variadic_callee(0, *p); } // CHECK-AAPCS: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 16 dereferenceable(16) %byval-temp, ptr noundef nonnull align 16 dereferenceable(16) %p, i64 16, i1 false) -// CHECK-AAPCS: call void (i32, ...) @small_pst_variadic_callee(i32 noundef 0, ptr noundef nonnull %byval-temp) +// CHECK-AAPCS: call void (i32, ...) @small_pst_variadic_callee(i32 noundef 0, ptr dead_on_return noundef nonnull %byval-temp) // CHECK-DARWIN: %0 = load i128, ptr %p, align 16 // CHECK-DARWIN: tail call void (i32, ...) @small_pst_variadic_callee(i32 noundef 0, i128 %0) @@ -467,7 +467,7 @@ void test_tuple_reg_count(svfloat32_t x, svfloat32x2_t y) { svfloat32_t, svfloat32_t, svfloat32_t, svfloat32x2_t); test_tuple_reg_count_callee(x, x, x, x, x, x, x, y); } -// CHECK-AAPCS: declare void @test_tuple_reg_count_callee(, , , , , , , ptr noundef) +// CHECK-AAPCS: declare void @test_tuple_reg_count_callee(, , , , , , , ptr dead_on_return noundef) // CHECK-DARWIN: declare void @test_tuple_reg_count_callee(, , , , , , , , ) // Regression test for incorrect passing of SVE vector tuples @@ -476,5 +476,5 @@ void test_tuple_reg_count_bool(svboolx4_t x, svboolx4_t y) { void test_tuple_reg_count_bool_callee(svboolx4_t, svboolx4_t); test_tuple_reg_count_bool_callee(x, y); } -// CHECK-AAPCS: declare void @test_tuple_reg_count_bool_callee(, , , , ptr noundef) +// CHECK-AAPCS: declare void @test_tuple_reg_count_bool_callee(, , , , ptr dead_on_return noundef) // CHECK-DARWIN: declare void @test_tuple_reg_count_bool_callee(, , , , , , , ) diff --git a/clang/test/CodeGen/AArch64/struct-coerce-using-ptr.cpp b/clang/test/CodeGen/AArch64/struct-coerce-using-ptr.cpp index b1232921df363..f0c9ef28201a5 100644 --- a/clang/test/CodeGen/AArch64/struct-coerce-using-ptr.cpp +++ b/clang/test/CodeGen/AArch64/struct-coerce-using-ptr.cpp @@ -82,7 +82,7 @@ struct Sppp { int *x, *y, *z; }; // CHECK-A64-LABEL: define dso_local void @_Z4Tppp4Sppp( -// CHECK-A64-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] { +// CHECK-A64-SAME: ptr dead_on_return noundef [[S:%.*]]) #[[ATTR0]] { // CHECK-A64-NEXT: [[ENTRY:.*:]] // CHECK-A64-NEXT: [[S_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 // CHECK-A64-NEXT: store ptr [[S]], ptr [[S_INDIRECT_ADDR]], align 8 @@ -490,7 +490,7 @@ struct Spa3 { int* xs[3]; }; // CHECK-A64-LABEL: define dso_local void @_Z4Tpa34Spa3( -// CHECK-A64-SAME: ptr noundef [[S:%.*]]) #[[ATTR0]] { +// CHECK-A64-SAME: ptr dead_on_return noundef [[S:%.*]]) #[[ATTR0]] { // CHECK-A64-NEXT: [[ENTRY:.*:]] // CHECK-A64-NEXT: [[S_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 // CHECK-A64-NEXT: store ptr [[S]], ptr [[S_INDIRECT_ADDR]], align 8 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 index c3d0541229fac..d244a8ba88572 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 @@ -58,7 +58,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 writable writeonly sret(<[[#div(VBITS,8)]] x i8>) align 16 captures(none) initializes((0, [[#div(VBITS,8)]])) %agg.result, ptr noundef readonly captures(none) %0) +// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(<[[#div(VBITS,8)]] x i8>) align 16 captures(none) initializes((0, [[#div(VBITS,8)]])) %agg.result, ptr dead_on_return noundef readonly captures(none) %0) // CHECK-NEXT: entry: // CHECK-NEXT: [[X:%.*]] = load <[[#div(VBITS,8)]] x i8>, ptr [[TMP0:%.*]], align 16, [[TBAA6:!tbaa !.*]] // CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = tail call @llvm.vector.insert.nxv16i8.v[[#div(VBITS,8)]]i8( poison, <[[#div(VBITS,8)]] x i8> [[X]], i64 0) @@ -88,13 +88,13 @@ typedef svint8_t vec2 __attribute__((arm_sve_vector_bits(N))); // CHECK-NEXT: [[X:%.*]] = tail call <[[#div(VBITS,8)]] x i8> @llvm.vector.extract.v[[#div(VBITS,8)]]i8.nxv16i8( [[X_COERCE:%.*]], i64 0) // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 [[SIZE:[0-9]+]], ptr nonnull [[INDIRECT_ARG_TEMP]]) #[[ATTR6:[0-9]+]] // CHECK-NEXT: store <[[#div(VBITS,8)]] x i8> [[X]], ptr [[INDIRECT_ARG_TEMP]], align 16, [[TBAA6]] -// CHECK-NEXT: call void @f3(ptr noundef nonnull [[INDIRECT_ARG_TEMP]]) [[ATTR5:#.*]] +// CHECK-NEXT: call void @f3(ptr dead_on_return noundef nonnull [[INDIRECT_ARG_TEMP]]) [[ATTR5:#.*]] // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 [[SIZE]], ptr nonnull [[INDIRECT_ARG_TEMP]]) #[[ATTR6:[0-9]+]] // CHECK-NEXT: ret void // CHECK128-LABEL: declare void @f3(<16 x i8> noundef) // CHECK-LABEL: declare void @f3( -// CHECK-SAME: ptr noundef) +// CHECK-SAME: ptr dead_on_return noundef) void g(vec2 x) { f3(x); } // OK #endif 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 index e82069aab2486..d42ecb663050f 100644 --- 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 @@ -75,7 +75,7 @@ typedef svint16_t vec2 __attribute__((arm_sve_vector_bits(N))); // CHECKWIDE-NEXT: [[X:%.*]] = tail call <[[#div(VBITS, 16)]] x i16> @llvm.vector.extract.v[[#div(VBITS, 16)]]i16.nxv8i16( [[X_COERCE:%.*]], i64 0) // CHECKWIDE-NEXT: call void @llvm.lifetime.start.p0(i64 [[SIZE:[0-9]+]], ptr nonnull [[INDIRECT_ARG_TEMP]]) #[[ATTR6:[0-9]+]] // CHECKWIDE-NEXT: store <[[#div(VBITS, 16)]] x i16> [[X]], ptr [[INDIRECT_ARG_TEMP]], align 16, [[TBAA6:!tbaa !.*]] -// CHECKWIDE-NEXT: call void @_Z1fDv[[#div(VBITS, 16)]]_s(ptr noundef nonnull [[INDIRECT_ARG_TEMP]]) [[ATTR5:#.*]] +// CHECKWIDE-NEXT: call void @_Z1fDv[[#div(VBITS, 16)]]_s(ptr dead_on_return noundef nonnull [[INDIRECT_ARG_TEMP]]) [[ATTR5:#.*]] // CHECKWIDE-NEXT: call void @llvm.lifetime.end.p0(i64 [[SIZE]], ptr nonnull [[INDIRECT_ARG_TEMP]]) #[[ATTR6:[0-9]+]] // CHECKWIDE-NEXT: ret void void g(vec2 x) { f(x); } // OK diff --git a/clang/test/CodeGen/LoongArch/bitint.c b/clang/test/CodeGen/LoongArch/bitint.c index f346f569d0eb0..950f5308e32cc 100644 --- a/clang/test/CodeGen/LoongArch/bitint.c +++ b/clang/test/CodeGen/LoongArch/bitint.c @@ -26,12 +26,12 @@ void pass_BitInt129(_BitInt(129)); // LA32-NEXT: [[LOADEDV1:%.*]] = trunc i128 [[TMP1]] to i65 // LA32-NEXT: [[STOREDV:%.*]] = sext i65 [[LOADEDV1]] to i128 // LA32-NEXT: store i128 [[STOREDV]], ptr [[BYVAL_TEMP]], align 16 -// LA32-NEXT: call void @pass_BitInt65(ptr noundef [[BYVAL_TEMP]]) +// LA32-NEXT: call void @pass_BitInt65(ptr dead_on_return noundef [[BYVAL_TEMP]]) // LA32-NEXT: [[TMP2:%.*]] = load i256, ptr [[L129]], align 16 // LA32-NEXT: [[LOADEDV2:%.*]] = trunc i256 [[TMP2]] to i129 // LA32-NEXT: [[STOREDV4:%.*]] = sext i129 [[LOADEDV2]] to i256 // LA32-NEXT: store i256 [[STOREDV4]], ptr [[BYVAL_TEMP3]], align 16 -// LA32-NEXT: call void @pass_BitInt129(ptr noundef [[BYVAL_TEMP3]]) +// LA32-NEXT: call void @pass_BitInt129(ptr dead_on_return noundef [[BYVAL_TEMP3]]) // LA32-NEXT: ret void // // LA64-LABEL: define dso_local void @example_BitInt( @@ -54,7 +54,7 @@ void pass_BitInt129(_BitInt(129)); // LA64-NEXT: [[LOADEDV2:%.*]] = trunc i256 [[TMP2]] to i129 // LA64-NEXT: [[STOREDV:%.*]] = sext i129 [[LOADEDV2]] to i256 // LA64-NEXT: store i256 [[STOREDV]], ptr [[BYVAL_TEMP]], align 16 -// LA64-NEXT: call void @pass_BitInt129(ptr noundef [[BYVAL_TEMP]]) +// LA64-NEXT: call void @pass_BitInt129(ptr dead_on_return noundef [[BYVAL_TEMP]]) // LA64-NEXT: ret void // void example_BitInt(void) { diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-fpconstrained.c b/clang/test/CodeGen/PowerPC/builtins-ppc-fpconstrained.c index 838db02415fe5..b46fa9f2cf157 100644 --- a/clang/test/CodeGen/PowerPC/builtins-ppc-fpconstrained.c +++ b/clang/test/CodeGen/PowerPC/builtins-ppc-fpconstrained.c @@ -11,7 +11,7 @@ // RUN: -S -ffp-exception-behavior=strict \ // RUN: -o - %s | FileCheck --check-prefix=CHECK-ASM \ // RUN: --check-prefix=FIXME-CHECK %s -// RUN: %clang_cc1 -triple powerpcspe -ffp-exception-behavior=strict \ +// RUN: %clang_cc1 -triple powerpc -ffp-exception-behavior=strict \ // RUN: -target-feature +vsx -fexperimental-strict-floating-point -emit-llvm \ // RUN: %s -o - | FileCheck --check-prefix=CHECK-CONSTRAINED %s diff --git a/clang/test/CodeGen/PowerPC/ppc-dmf-future-builtin-err.c b/clang/test/CodeGen/PowerPC/ppc-dmf-future-builtin-err.c deleted file mode 100644 index 9def39f5fa479..0000000000000 --- a/clang/test/CodeGen/PowerPC/ppc-dmf-future-builtin-err.c +++ /dev/null @@ -1,15 +0,0 @@ -// RUN: not %clang_cc1 -triple powerpc64le-unknown-linux-gnu -target-cpu pwr10 \ -// RUN: %s -emit-llvm-only 2>&1 | FileCheck %s - -__attribute__((target("no-mma"))) -void test_mma(unsigned char *vdmrp, unsigned char *vpp, vector unsigned char vc) { - __dmr1024 vdmr = *((__dmr1024 *)vdmrp); - __vector_pair vp = *((__vector_pair *)vpp); - __builtin_mma_dmsetdmrz(&vdmr); - __builtin_mma_dmmr(&vdmr, (__dmr1024*)vpp); - __builtin_mma_dmxor(&vdmr, (__dmr1024*)vpp); - -// CHECK: error: '__builtin_mma_dmsetdmrz' needs target feature mma,isa-future-instructions -// CHECK: error: '__builtin_mma_dmmr' needs target feature mma,isa-future-instructions -// CHECK: error: '__builtin_mma_dmxor' needs target feature mma,isa-future-instructions -} diff --git a/clang/test/CodeGen/PowerPC/ppc-dmf-mma-builtin-err.c b/clang/test/CodeGen/PowerPC/ppc-dmf-mma-builtin-err.c index c02274696244a..5a92d6e982511 100644 --- a/clang/test/CodeGen/PowerPC/ppc-dmf-mma-builtin-err.c +++ b/clang/test/CodeGen/PowerPC/ppc-dmf-mma-builtin-err.c @@ -1,3 +1,5 @@ +// RUN: not %clang_cc1 -triple powerpc64le-unknown-linux-gnu -target-cpu pwr10 \ +// RUN: %s -emit-llvm-only 2>&1 | FileCheck %s // RUN: not %clang_cc1 -triple powerpc64le-unknown-linux-gnu -target-cpu future \ // RUN: %s -emit-llvm-only 2>&1 | FileCheck %s diff --git a/clang/test/CodeGen/PowerPC/ppc64-vector.c b/clang/test/CodeGen/PowerPC/ppc64-vector.c index 5d3dd86a009d5..2e99781f84910 100644 --- a/clang/test/CodeGen/PowerPC/ppc64-vector.c +++ b/clang/test/CodeGen/PowerPC/ppc64-vector.c @@ -39,7 +39,7 @@ v8i16 test_v8i16(v8i16 x) return x; } -// CHECK: define{{.*}} void @test_v16i16(ptr dead_on_unwind noalias writable sret(<16 x i16>) align 32 %agg.result, ptr noundef %0) +// CHECK: define{{.*}} void @test_v16i16(ptr dead_on_unwind noalias writable sret(<16 x i16>) align 32 %agg.result, ptr dead_on_return noundef %0) v16i16 test_v16i16(v16i16 x) { return x; diff --git a/clang/test/CodeGen/RISCV/riscv-abi.cpp b/clang/test/CodeGen/RISCV/riscv-abi.cpp index fe1a2b6d8595c..d2e080829e72f 100644 --- a/clang/test/CodeGen/RISCV/riscv-abi.cpp +++ b/clang/test/CodeGen/RISCV/riscv-abi.cpp @@ -75,7 +75,7 @@ struct child3_int64_s : parent3_float_s { }; // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @_Z30float_int64_struct_inheritance14child3_int64_s -// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_CHILD3_INT64_S:%.*]]) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_CHILD3_INT64_S:%.*]]) align 8 [[AGG_RESULT:%.*]], ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // // LP64-LABEL: define dso_local [2 x i64] @_Z30float_int64_struct_inheritance14child3_int64_s @@ -99,7 +99,7 @@ struct child4_double_s : parent4_double_s { }; // ILP32-ILP32F-LABEL: define dso_local void @_Z32double_double_struct_inheritance15child4_double_s -// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_CHILD4_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_CHILD4_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]], ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, double } @_Z32double_double_struct_inheritance15child4_double_s @@ -130,11 +130,11 @@ struct child5_virtual_s : virtual parent5_virtual_s { }; // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @_Z38int32_float_virtual_struct_inheritance16child5_virtual_s -// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_CHILD5_VIRTUAL_S:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_CHILD5_VIRTUAL_S:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // // LP64-LP64F-LP64D-LABEL: define dso_local void @_Z38int32_float_virtual_struct_inheritance16child5_virtual_s -// LP64-LP64F-LP64D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_CHILD5_VIRTUAL_S:%.*]]) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]]) #[[ATTR0]] { +// LP64-LP64F-LP64D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_CHILD5_VIRTUAL_S:%.*]]) align 8 [[AGG_RESULT:%.*]], ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // LP64-LP64F-LP64D: entry: // struct child5_virtual_s int32_float_virtual_struct_inheritance(struct child5_virtual_s a) { diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c index 82e43fff0c3aa..bc89cb532bdcc 100644 --- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c +++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c @@ -138,7 +138,7 @@ struct st_i32x4x9 { typedef int __attribute__((vector_size(256))) int32x64_t; -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_too_large(ptr noundef %0) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_too_large(ptr dead_on_return noundef %0) void __attribute__((riscv_vls_cc)) test_too_large(int32x64_t arg) {} // CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_too_large_256( noundef %arg.coerce) void __attribute__((riscv_vls_cc(256))) test_too_large_256(int32x64_t arg) {} @@ -173,9 +173,9 @@ void __attribute__((riscv_vls_cc)) test_st_i32x8x2(struct st_i32x8x2 arg) {} // CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x8x2_256(target("riscv.vector.tuple", , 2) %arg) void __attribute__((riscv_vls_cc(256))) test_st_i32x8x2_256(struct st_i32x8x2 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x64x2(ptr noundef %arg) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x64x2(ptr dead_on_return noundef %arg) void __attribute__((riscv_vls_cc)) test_st_i32x64x2(struct st_i32x64x2 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x64x2_256(ptr noundef %arg) +// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x64x2_256(ptr dead_on_return noundef %arg) void __attribute__((riscv_vls_cc(256))) test_st_i32x64x2_256(struct st_i32x64x2 arg) {} // CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4x3(target("riscv.vector.tuple", , 3) %arg) @@ -188,7 +188,7 @@ void __attribute__((riscv_vls_cc)) test_st_i32x4x8(struct st_i32x4x8 arg) {} // CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x4x8_256(target("riscv.vector.tuple", , 8) %arg) void __attribute__((riscv_vls_cc(256))) test_st_i32x4x8_256(struct st_i32x4x8 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4x9(ptr noundef %arg) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4x9(ptr dead_on_return noundef %arg) void __attribute__((riscv_vls_cc)) test_st_i32x4x9(struct st_i32x4x9 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x4x9_256(ptr noundef %arg) +// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x4x9_256(ptr dead_on_return noundef %arg) void __attribute__((riscv_vls_cc(256))) test_st_i32x4x9_256(struct st_i32x4x9 arg) {} diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp index 5f6539796c20d..128610e578c26 100644 --- a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp +++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp @@ -118,7 +118,7 @@ struct st_i32x4x9 { typedef int __attribute__((vector_size(256))) int32x64_t; -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z14test_too_largeDv64_i(ptr noundef %0) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z14test_too_largeDv64_i(ptr dead_on_return noundef %0) [[riscv::vls_cc]] void test_too_large(int32x64_t arg) {} // CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z18test_too_large_256Dv64_i( noundef %arg.coerce) [[riscv::vls_cc(256)]] void test_too_large_256(int32x64_t arg) {} @@ -153,9 +153,9 @@ typedef int __attribute__((vector_size(256))) int32x64_t; // CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z19test_st_i32x8x2_25610st_i32x8x2(target("riscv.vector.tuple", , 2) %arg) [[riscv::vls_cc(256)]] void test_st_i32x8x2_256(struct st_i32x8x2 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z16test_st_i32x64x211st_i32x64x2(ptr noundef %arg) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z16test_st_i32x64x211st_i32x64x2(ptr dead_on_return noundef %arg) [[riscv::vls_cc]] void test_st_i32x64x2(struct st_i32x64x2 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z20test_st_i32x64x2_25611st_i32x64x2(ptr noundef %arg) +// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z20test_st_i32x64x2_25611st_i32x64x2(ptr dead_on_return noundef %arg) [[riscv::vls_cc(256)]] void test_st_i32x64x2_256(struct st_i32x64x2 arg) {} // CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z15test_st_i32x4x310st_i32x4x3(target("riscv.vector.tuple", , 3) %arg) @@ -168,7 +168,7 @@ typedef int __attribute__((vector_size(256))) int32x64_t; // CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z19test_st_i32x4x8_25610st_i32x4x8(target("riscv.vector.tuple", , 8) %arg) [[riscv::vls_cc(256)]] void test_st_i32x4x8_256(struct st_i32x4x8 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z15test_st_i32x4x910st_i32x4x9(ptr noundef %arg) +// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @_Z15test_st_i32x4x910st_i32x4x9(ptr dead_on_return noundef %arg) [[riscv::vls_cc]] void test_st_i32x4x9(struct st_i32x4x9 arg) {} -// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z19test_st_i32x4x9_25610st_i32x4x9(ptr noundef %arg) +// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @_Z19test_st_i32x4x9_25610st_i32x4x9(ptr dead_on_return noundef %arg) [[riscv::vls_cc(256)]] void test_st_i32x4x9_256(struct st_i32x4x9 arg) {} diff --git a/clang/test/CodeGen/RISCV/riscv32-abi.c b/clang/test/CodeGen/RISCV/riscv32-abi.c index b53f9a9169146..a9e56d40817ae 100644 --- a/clang/test/CodeGen/RISCV/riscv32-abi.c +++ b/clang/test/CodeGen/RISCV/riscv32-abi.c @@ -246,7 +246,7 @@ struct large { }; // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_large -// ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[X:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[X:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // void f_agg_large(struct large x) { @@ -266,7 +266,7 @@ struct large f_agg_large_ret(int32_t i, int8_t j) { typedef unsigned char v16i8 __attribute__((vector_size(16))); // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_vec_large_v16i8 -// ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[TMP0:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[TMP0:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // void f_vec_large_v16i8(v16i8 x) { @@ -285,7 +285,7 @@ v16i8 f_vec_large_v16i8_ret(void) { // if they were passed in registers. // ILP32-ILP32F-ILP32D-LABEL: define dso_local i32 @f_scalar_stack_1 -// ILP32-ILP32F-ILP32D-SAME: (i32 [[A_COERCE:%.*]], [2 x i32] [[B_COERCE:%.*]], i64 [[C_COERCE:%.*]], ptr noundef [[D:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]], i8 noundef signext [[H:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (i32 [[A_COERCE:%.*]], [2 x i32] [[B_COERCE:%.*]], i64 [[C_COERCE:%.*]], ptr dead_on_return noundef [[D:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]], i8 noundef signext [[H:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // int f_scalar_stack_1(struct tiny a, struct small b, struct small_aligned c, @@ -343,7 +343,7 @@ struct large f_scalar_stack_6(float a, int64_t b, double c, long double d, // they would be if passed via registers. // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_stack -// ILP32-ILP32F-ILP32D-SAME: (double noundef [[A:%.*]], i64 noundef [[B:%.*]], double noundef [[C:%.*]], i64 noundef [[D:%.*]], i32 [[E_COERCE:%.*]], [2 x i32] [[F_COERCE:%.*]], i64 [[G_COERCE:%.*]], ptr noundef [[H:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (double noundef [[A:%.*]], i64 noundef [[B:%.*]], double noundef [[C:%.*]], i64 noundef [[D:%.*]], i32 [[E_COERCE:%.*]], [2 x i32] [[F_COERCE:%.*]], i64 [[G_COERCE:%.*]], ptr dead_on_return noundef [[H:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // void f_agg_stack(double a, int64_t b, double c, int64_t d, struct tiny e, @@ -366,7 +366,7 @@ struct double_int8_s { double d; int64_t i; }; struct int_double_s { int a; double b; }; // ILP32-ILP32F-LABEL: define dso_local void @f_int_double_s_arg -// ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local void @f_int_double_s_arg @@ -482,7 +482,7 @@ struct zbf_double_zbf_s f_ret_zbf_double_zbf_s(void) { struct double_float_s { double f; float g; }; // ILP32-ILP32F-LABEL: define dso_local void @f_double_double_s_arg -// ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local void @f_double_double_s_arg @@ -504,7 +504,7 @@ struct double_double_s f_ret_double_double_s(void) { } // ILP32-ILP32F-LABEL: define dso_local void @f_double_float_s_arg -// ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local void @f_double_float_s_arg @@ -526,7 +526,7 @@ struct double_float_s f_ret_double_float_s(void) { } // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_double_double_s_arg_insufficient_fprs -// ILP32-ILP32F-ILP32D-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], ptr noundef [[H:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], ptr dead_on_return noundef [[H:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // void f_double_double_s_arg_insufficient_fprs(float a, double b, double c, double d, @@ -543,7 +543,7 @@ struct double_int64bf_s { double d; int64_t i : 32; }; struct double_int8_zbf_s { double d; int8_t i; int : 0; }; // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_double_int8_s_arg -// ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // void f_double_int8_s_arg(struct double_int8_s a) {} @@ -557,7 +557,7 @@ struct double_int8_s f_ret_double_int8_s(void) { } // ILP32-ILP32F-LABEL: define dso_local void @f_double_uint8_s_arg -// ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local void @f_double_uint8_s_arg @@ -579,7 +579,7 @@ struct double_uint8_s f_ret_double_uint8_s(void) { } // ILP32-ILP32F-LABEL: define dso_local void @f_double_int32_s_arg -// ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local void @f_double_int32_s_arg @@ -601,7 +601,7 @@ struct double_int32_s f_ret_double_int32_s(void) { } // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_double_int64_s_arg -// ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // void f_double_int64_s_arg(struct double_int64_s a) {} @@ -615,7 +615,7 @@ struct double_int64_s f_ret_double_int64_s(void) { } // ILP32-ILP32F-LABEL: define dso_local void @f_double_int64bf_s_arg -// ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local void @f_double_int64bf_s_arg @@ -640,7 +640,7 @@ struct double_int64bf_s f_ret_double_int64bf_s(void) { // floating point calling convention. // ILP32-ILP32F-LABEL: define dso_local void @f_double_int8_zbf_s -// ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local void @f_double_int8_zbf_s @@ -662,14 +662,14 @@ struct double_int8_zbf_s f_ret_double_int8_zbf_s(void) { } // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_double_int8_s_arg_insufficient_gprs -// ILP32-ILP32F-ILP32D-SAME: (i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], i32 noundef [[H:%.*]], ptr noundef [[I:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], i32 noundef [[H:%.*]], ptr dead_on_return noundef [[I:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // void f_double_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e, int f, int g, int h, struct double_int8_s i) {} // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_struct_double_int8_insufficient_fprs -// ILP32-ILP32F-ILP32D-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], double noundef [[H:%.*]], ptr noundef [[I:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], double noundef [[H:%.*]], ptr dead_on_return noundef [[I:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // void f_struct_double_int8_insufficient_fprs(float a, double b, double c, double d, @@ -679,7 +679,7 @@ void f_struct_double_int8_insufficient_fprs(float a, double b, double c, double // floating-point value should be passed as if it were an fp+fp struct. // ILP32-ILP32F-LABEL: define dso_local void @f_doublecomplex -// ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local void @f_doublecomplex @@ -703,7 +703,7 @@ double __complex__ f_ret_doublecomplex(void) { struct doublecomplex_s { double __complex__ c; }; // ILP32-ILP32F-LABEL: define dso_local void @f_doublecomplex_s_arg -// ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local void @f_doublecomplex_s_arg @@ -754,7 +754,7 @@ struct doublearr1_s f_ret_doublearr1_s(void) { struct doublearr2_s { double a[2]; }; // ILP32-ILP32F-LABEL: define dso_local void @f_doublearr2_s_arg -// ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local void @f_doublearr2_s_arg @@ -778,7 +778,7 @@ struct doublearr2_s f_ret_doublearr2_s(void) { struct doublearr2_tricky1_s { struct { double f[1]; } g[2]; }; // ILP32-ILP32F-LABEL: define dso_local void @f_doublearr2_tricky1_s_arg -// ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local void @f_doublearr2_tricky1_s_arg @@ -802,7 +802,7 @@ struct doublearr2_tricky1_s f_ret_doublearr2_tricky1_s(void) { struct doublearr2_tricky2_s { struct {}; struct { double f[1]; } g[2]; }; // ILP32-ILP32F-LABEL: define dso_local void @f_doublearr2_tricky2_s_arg -// ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local void @f_doublearr2_tricky2_s_arg @@ -826,7 +826,7 @@ struct doublearr2_tricky2_s f_ret_doublearr2_tricky2_s(void) { struct doublearr2_tricky3_s { union {}; struct { double f[1]; } g[2]; }; // ILP32-ILP32F-LABEL: define dso_local void @f_doublearr2_tricky3_s_arg -// ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local void @f_doublearr2_tricky3_s_arg @@ -850,7 +850,7 @@ struct doublearr2_tricky3_s f_ret_doublearr2_tricky3_s(void) { struct doublearr2_tricky4_s { union {}; struct { struct {}; double f[1]; } g[2]; }; // ILP32-ILP32F-LABEL: define dso_local void @f_doublearr2_tricky4_s_arg -// ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local void @f_doublearr2_tricky4_s_arg @@ -877,7 +877,7 @@ struct doublearr2_tricky4_s f_ret_doublearr2_tricky4_s(void) { struct int_double_int_s { int a; double b; int c; }; // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int_double_int_s_arg -// ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // void f_int_double_int_s_arg(struct int_double_int_s a) {} @@ -893,7 +893,7 @@ struct int_double_int_s f_ret_int_double_int_s(void) { struct int64_double_s { int64_t a; double b; }; // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int64_double_s_arg -// ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // void f_int64_double_s_arg(struct int64_double_s a) {} @@ -909,7 +909,7 @@ struct int64_double_s f_ret_int64_double_s(void) { struct char_char_double_s { char a; char b; double c; }; // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_char_char_double_s_arg -// ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // void f_char_char_double_s_arg(struct char_char_double_s a) {} @@ -948,7 +948,7 @@ union double_u f_ret_double_u(void) { // double+double structs by the ABI. // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_int32_s_double_int32_s_just_sufficient_gprs -// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_INT32_S:%.*]]) align 8 [[AGG_RESULT:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], ptr noundef [[H:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_INT32_S:%.*]]) align 8 [[AGG_RESULT:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], ptr dead_on_return noundef [[H:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, i32 } @f_ret_double_int32_s_double_int32_s_just_sufficient_gprs @@ -961,7 +961,7 @@ struct double_int32_s f_ret_double_int32_s_double_int32_s_just_sufficient_gprs( } // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_double_s_double_int32_s_just_sufficient_gprs -// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], ptr noundef [[H:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], ptr dead_on_return noundef [[H:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, double } @f_ret_double_double_s_double_int32_s_just_sufficient_gprs @@ -974,7 +974,7 @@ struct double_double_s f_ret_double_double_s_double_int32_s_just_sufficient_gprs } // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublecomplex_double_int32_s_just_sufficient_gprs -// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], ptr noundef [[H:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], ptr dead_on_return noundef [[H:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublecomplex_double_int32_s_just_sufficient_gprs @@ -1189,7 +1189,7 @@ struct float_int32_s f_ret_float_int32_s(void) { } // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_float_int64_s_arg -// ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // void f_float_int64_s_arg(struct float_int64_s a) {} @@ -1465,7 +1465,7 @@ struct floatarr2_tricky4_s f_ret_floatarr2_tricky4_s(void) { struct int_float_int_s { int a; float b; int c; }; // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int_float_int_s_arg -// ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // void f_int_float_int_s_arg(struct int_float_int_s a) {} @@ -1481,7 +1481,7 @@ struct int_float_int_s f_ret_int_float_int_s(void) { struct int64_float_s { int64_t a; float b; }; // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int64_float_s_arg -// ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // void f_int64_float_s_arg(struct int64_float_s a) {} @@ -1619,7 +1619,7 @@ struct zbf_float16_zbf_s f_ret_zbf_float16_zbf_s(void) { struct double_float16_s { double f; _Float16 g; }; // ILP32-ILP32F-LABEL: define dso_local void @f_double_float16_s_arg -// ILP32-ILP32F-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local void @f_double_float16_s_arg @@ -1641,7 +1641,7 @@ struct double_float16_s f_ret_double_float16_s(void) { } // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_double_float16_s_arg_insufficient_fprs -// ILP32-ILP32F-ILP32D-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], ptr noundef [[H:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], double noundef [[C:%.*]], double noundef [[D:%.*]], double noundef [[E:%.*]], double noundef [[F:%.*]], double noundef [[G:%.*]], ptr dead_on_return noundef [[H:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // void f_double_float16_s_arg_insufficient_fprs(float a, double b, double c, double d, @@ -1725,7 +1725,7 @@ struct float16_int32_s f_ret_float16_int32_s(void) { } // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_float16_int64_s_arg -// ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // void f_float16_int64_s_arg(struct float16_int64_s a) {} @@ -2001,7 +2001,7 @@ struct float16arr2_tricky4_s f_ret_float16arr2_tricky4_s(void) { struct int_float16_int_s { int a; _Float16 b; int c; }; // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int_float16_int_s_arg -// ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // void f_int_float16_int_s_arg(struct int_float16_int_s a) {} @@ -2017,7 +2017,7 @@ struct int_float16_int_s f_ret_int_float16_int_s(void) { struct int64_float16_s { int64_t a; _Float16 b; }; // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_int64_float16_s_arg -// ILP32-ILP32F-ILP32D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // void f_int64_float16_s_arg(struct int64_float16_s a) {} diff --git a/clang/test/CodeGen/RISCV/riscv32-vararg.c b/clang/test/CodeGen/RISCV/riscv32-vararg.c index 2b332410f8637..ed301f9269bb8 100644 --- a/clang/test/CodeGen/RISCV/riscv32-vararg.c +++ b/clang/test/CodeGen/RISCV/riscv32-vararg.c @@ -64,7 +64,7 @@ int f_va_callee(int, ...); // CHECK-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_SMALL_ALIGNED]], ptr [[DOTCOMPOUNDLITERAL4]], i32 0, i32 0 // CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[COERCE_DIVE]], align 8 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[BYVAL_TEMP]], ptr align 4 [[DOTCOMPOUNDLITERAL6]], i32 16, i1 false) -// CHECK-NEXT: [[CALL:%.*]] = call i32 (i32, ...) @f_va_callee(i32 noundef 1, i32 noundef 2, i64 noundef 3, double noundef 4.000000e+00, double noundef 5.000000e+00, i32 [[TMP0]], [2 x i32] [[TMP1]], i64 [[TMP2]], ptr noundef [[BYVAL_TEMP]]) +// CHECK-NEXT: [[CALL:%.*]] = call i32 (i32, ...) @f_va_callee(i32 noundef 1, i32 noundef 2, i64 noundef 3, double noundef 4.000000e+00, double noundef 5.000000e+00, i32 [[TMP0]], [2 x i32] [[TMP1]], i64 [[TMP2]], ptr dead_on_return noundef [[BYVAL_TEMP]]) // CHECK-NEXT: ret void // void f_va_caller(void) { diff --git a/clang/test/CodeGen/RISCV/riscv64-abi.c b/clang/test/CodeGen/RISCV/riscv64-abi.c index 021565238904e..dc01750e56970 100644 --- a/clang/test/CodeGen/RISCV/riscv64-abi.c +++ b/clang/test/CodeGen/RISCV/riscv64-abi.c @@ -242,7 +242,7 @@ struct large { }; // LP64-LP64F-LP64D-LABEL: define dso_local void @f_agg_large -// LP64-LP64F-LP64D-SAME: (ptr noundef [[X:%.*]]) #[[ATTR0]] { +// LP64-LP64F-LP64D-SAME: (ptr dead_on_return noundef [[X:%.*]]) #[[ATTR0]] { // LP64-LP64F-LP64D: entry: // void f_agg_large(struct large x) { @@ -262,7 +262,7 @@ struct large f_agg_large_ret(int32_t i, int8_t j) { typedef unsigned char v32i8 __attribute__((vector_size(32))); // LP64-LP64F-LP64D-LABEL: define dso_local void @f_vec_large_v32i8 -// LP64-LP64F-LP64D-SAME: (ptr noundef [[TMP0:%.*]]) #[[ATTR0]] { +// LP64-LP64F-LP64D-SAME: (ptr dead_on_return noundef [[TMP0:%.*]]) #[[ATTR0]] { // LP64-LP64F-LP64D: entry: // void f_vec_large_v32i8(v32i8 x) { @@ -281,7 +281,7 @@ v32i8 f_vec_large_v32i8_ret(void) { // if they were passed in registers. // LP64-LP64F-LP64D-LABEL: define dso_local signext i32 @f_scalar_stack_1 -// LP64-LP64F-LP64D-SAME: (i64 [[A_COERCE:%.*]], [2 x i64] [[B_COERCE:%.*]], i128 [[C_COERCE:%.*]], ptr noundef [[D:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]], i8 noundef signext [[H:%.*]]) #[[ATTR0]] { +// LP64-LP64F-LP64D-SAME: (i64 [[A_COERCE:%.*]], [2 x i64] [[B_COERCE:%.*]], i128 [[C_COERCE:%.*]], ptr dead_on_return noundef [[D:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]], i8 noundef signext [[H:%.*]]) #[[ATTR0]] { // LP64-LP64F-LP64D: entry: // int f_scalar_stack_1(struct tiny a, struct small b, struct small_aligned c, @@ -290,7 +290,7 @@ int f_scalar_stack_1(struct tiny a, struct small b, struct small_aligned c, } // LP64-LP64F-LP64D-LABEL: define dso_local signext i32 @f_scalar_stack_2 -// LP64-LP64F-LP64D-SAME: (i32 noundef signext [[A:%.*]], i128 noundef [[B:%.*]], i64 noundef [[C:%.*]], fp128 noundef [[D:%.*]], ptr noundef [[TMP0:%.*]], i8 noundef zeroext [[F:%.*]], i8 noundef signext [[G:%.*]], i8 noundef zeroext [[H:%.*]]) #[[ATTR0]] { +// LP64-LP64F-LP64D-SAME: (i32 noundef signext [[A:%.*]], i128 noundef [[B:%.*]], i64 noundef [[C:%.*]], fp128 noundef [[D:%.*]], ptr dead_on_return noundef [[TMP0:%.*]], i8 noundef zeroext [[F:%.*]], i8 noundef signext [[G:%.*]], i8 noundef zeroext [[H:%.*]]) #[[ATTR0]] { // LP64-LP64F-LP64D: entry: // int f_scalar_stack_2(int32_t a, __int128_t b, int64_t c, long double d, v32i8 e, @@ -299,7 +299,7 @@ int f_scalar_stack_2(int32_t a, __int128_t b, int64_t c, long double d, v32i8 e, } // LP64-LP64F-LP64D-LABEL: define dso_local signext i32 @f_scalar_stack_3 -// LP64-LP64F-LP64D-SAME: (i32 noundef signext [[A:%.*]], i128 noundef [[B:%.*]], double noundef [[C:%.*]], fp128 noundef [[D:%.*]], ptr noundef [[TMP0:%.*]], i8 noundef zeroext [[F:%.*]], i8 noundef signext [[G:%.*]], i8 noundef zeroext [[H:%.*]]) #[[ATTR0]] { +// LP64-LP64F-LP64D-SAME: (i32 noundef signext [[A:%.*]], i128 noundef [[B:%.*]], double noundef [[C:%.*]], fp128 noundef [[D:%.*]], ptr dead_on_return noundef [[TMP0:%.*]], i8 noundef zeroext [[F:%.*]], i8 noundef signext [[G:%.*]], i8 noundef zeroext [[H:%.*]]) #[[ATTR0]] { // LP64-LP64F-LP64D: entry: // int f_scalar_stack_3(int32_t a, __int128_t b, double c, long double d, v32i8 e, @@ -312,7 +312,7 @@ int f_scalar_stack_3(int32_t a, __int128_t b, double c, long double d, v32i8 e, // to pass a pointer. // LP64-LP64F-LP64D-LABEL: define dso_local void @f_scalar_stack_4 -// LP64-LP64F-LP64D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_LARGE:%.*]]) align 8 [[AGG_RESULT:%.*]], i32 noundef signext [[A:%.*]], i128 noundef [[B:%.*]], fp128 noundef [[C:%.*]], ptr noundef [[TMP0:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]]) #[[ATTR0]] { +// LP64-LP64F-LP64D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_LARGE:%.*]]) align 8 [[AGG_RESULT:%.*]], i32 noundef signext [[A:%.*]], i128 noundef [[B:%.*]], fp128 noundef [[C:%.*]], ptr dead_on_return noundef [[TMP0:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]]) #[[ATTR0]] { // LP64-LP64F-LP64D: entry: // struct large f_scalar_stack_4(uint32_t a, __int128_t b, long double c, v32i8 d, @@ -321,7 +321,7 @@ struct large f_scalar_stack_4(uint32_t a, __int128_t b, long double c, v32i8 d, } // LP64-LP64F-LP64D-LABEL: define dso_local void @f_scalar_stack_5 -// LP64-LP64F-LP64D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_LARGE:%.*]]) align 8 [[AGG_RESULT:%.*]], double noundef [[A:%.*]], i128 noundef [[B:%.*]], fp128 noundef [[C:%.*]], ptr noundef [[TMP0:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]]) #[[ATTR0]] { +// LP64-LP64F-LP64D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_LARGE:%.*]]) align 8 [[AGG_RESULT:%.*]], double noundef [[A:%.*]], i128 noundef [[B:%.*]], fp128 noundef [[C:%.*]], ptr dead_on_return noundef [[TMP0:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]]) #[[ATTR0]] { // LP64-LP64F-LP64D: entry: // struct large f_scalar_stack_5(double a, __int128_t b, long double c, v32i8 d, @@ -330,7 +330,7 @@ struct large f_scalar_stack_5(double a, __int128_t b, long double c, v32i8 d, } // LP64-LP64F-LP64D-LABEL: define dso_local signext i32 @f_scalar_stack_6 -// LP64-LP64F-LP64D-SAME: (i32 noundef signext [[A:%.*]], i128 noundef [[B:%.*]], float noundef [[C:%.*]], fp128 noundef [[D:%.*]], ptr noundef [[TMP0:%.*]], i8 noundef zeroext [[F:%.*]], i8 noundef signext [[G:%.*]], i8 noundef zeroext [[H:%.*]], half noundef [[I:%.*]]) #[[ATTR0]] { +// LP64-LP64F-LP64D-SAME: (i32 noundef signext [[A:%.*]], i128 noundef [[B:%.*]], float noundef [[C:%.*]], fp128 noundef [[D:%.*]], ptr dead_on_return noundef [[TMP0:%.*]], i8 noundef zeroext [[F:%.*]], i8 noundef signext [[G:%.*]], i8 noundef zeroext [[H:%.*]], half noundef [[I:%.*]]) #[[ATTR0]] { // LP64-LP64F-LP64D: entry: // int f_scalar_stack_6(int32_t a, __int128_t b, float c, long double d, v32i8 e, @@ -1440,7 +1440,7 @@ struct doublearr2_tricky4_s f_ret_doublearr2_tricky4_s(void) { struct int_double_int_s { int a; double b; int c; }; // LP64-LP64F-LP64D-LABEL: define dso_local void @f_int_double_int_s_arg -// LP64-LP64F-LP64D-SAME: (ptr noundef [[A:%.*]]) #[[ATTR0]] { +// LP64-LP64F-LP64D-SAME: (ptr dead_on_return noundef [[A:%.*]]) #[[ATTR0]] { // LP64-LP64F-LP64D: entry: // void f_int_double_int_s_arg(struct int_double_int_s a) {} diff --git a/clang/test/CodeGen/RISCV/riscv64-vararg.c b/clang/test/CodeGen/RISCV/riscv64-vararg.c index a278f74ca4a86..17802553c795a 100644 --- a/clang/test/CodeGen/RISCV/riscv64-vararg.c +++ b/clang/test/CodeGen/RISCV/riscv64-vararg.c @@ -74,7 +74,7 @@ int f_va_callee(int, ...); // CHECK-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_SMALL_ALIGNED]], ptr [[DOTCOMPOUNDLITERAL4]], i32 0, i32 0 // CHECK-NEXT: [[TMP2:%.*]] = load i128, ptr [[COERCE_DIVE]], align 16 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[BYVAL_TEMP]], ptr align 8 [[DOTCOMPOUNDLITERAL6]], i64 32, i1 false) -// CHECK-NEXT: [[CALL:%.*]] = call signext i32 (i32, ...) @f_va_callee(i32 noundef signext 1, i32 noundef signext 2, i64 noundef 3, double noundef 4.000000e+00, double noundef 5.000000e+00, i64 [[TMP0]], [2 x i64] [[TMP1]], i128 [[TMP2]], ptr noundef [[BYVAL_TEMP]]) +// CHECK-NEXT: [[CALL:%.*]] = call signext i32 (i32, ...) @f_va_callee(i32 noundef signext 1, i32 noundef signext 2, i64 noundef 3, double noundef 4.000000e+00, double noundef 5.000000e+00, i64 [[TMP0]], [2 x i64] [[TMP1]], i128 [[TMP2]], ptr dead_on_return noundef [[BYVAL_TEMP]]) // CHECK-NEXT: [[CALL11:%.*]] = call signext i32 (i32, ...) @f_va_callee(i32 noundef signext 1, i32 noundef signext 2, i32 noundef signext 3, i32 noundef signext 4, fp128 noundef 0xL00000000000000004001400000000000, i32 noundef signext 6, i32 noundef signext 7, i32 noundef signext 8, i32 noundef signext 9) // CHECK-NEXT: [[A13:%.*]] = getelementptr inbounds nuw [[STRUCT_SMALL_ALIGNED]], ptr [[DOTCOMPOUNDLITERAL12]], i32 0, i32 0 // CHECK-NEXT: store i128 5, ptr [[A13]], align 16 diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/non-overloaded/vcompress.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/non-overloaded/vcompress.c new file mode 100644 index 0000000000000..6cff3dfbbb7dd --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/non-overloaded/vcompress.c @@ -0,0 +1,74 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +zve64x \ +// RUN: -target-feature +zvfbfmin -disable-O0-optnone \ +// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \ +// RUN: FileCheck --check-prefix=CHECK-RV64 %s + +#include + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16mf4( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv1bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vcompress_vm_bf16mf4(vbfloat16mf4_t vs2, vbool64_t vs1, + size_t vl) { + return __riscv_vcompress_vm_bf16mf4(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16mf2( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv2bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vcompress_vm_bf16mf2(vbfloat16mf2_t vs2, vbool32_t vs1, + size_t vl) { + return __riscv_vcompress_vm_bf16mf2(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16m1( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv4bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vcompress_vm_bf16m1(vbfloat16m1_t vs2, vbool16_t vs1, + size_t vl) { + return __riscv_vcompress_vm_bf16m1(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16m2( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv8bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vcompress_vm_bf16m2(vbfloat16m2_t vs2, vbool8_t vs1, + size_t vl) { + return __riscv_vcompress_vm_bf16m2(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16m4( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv16bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vcompress_vm_bf16m4(vbfloat16m4_t vs2, vbool4_t vs1, + size_t vl) { + return __riscv_vcompress_vm_bf16m4(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16m8( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv32bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vcompress_vm_bf16m8(vbfloat16m8_t vs2, vbool2_t vs1, + size_t vl) { + return __riscv_vcompress_vm_bf16m8(vs2, vs1, vl); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/non-overloaded/vrgather.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/non-overloaded/vrgather.c new file mode 100644 index 0000000000000..cb0004fa2b64d --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/non-overloaded/vrgather.c @@ -0,0 +1,272 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +zve64x \ +// RUN: -target-feature +zvfbfmin -disable-O0-optnone \ +// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \ +// RUN: FileCheck --check-prefix=CHECK-RV64 %s + +#include + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf4( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv1bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vv_bf16mf4(vbfloat16mf4_t vs2, vuint16mf4_t vs1, + size_t vl) { + return __riscv_vrgather_vv_bf16mf4(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf4( +// CHECK-RV64-SAME: [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv1bf16.i64( poison, [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vx_bf16mf4(vbfloat16mf4_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_vx_bf16mf4(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf2( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv2bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vv_bf16mf2(vbfloat16mf2_t vs2, vuint16mf2_t vs1, + size_t vl) { + return __riscv_vrgather_vv_bf16mf2(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf2( +// CHECK-RV64-SAME: [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv2bf16.i64( poison, [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vx_bf16mf2(vbfloat16mf2_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_vx_bf16mf2(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m1( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv4bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vv_bf16m1(vbfloat16m1_t vs2, vuint16m1_t vs1, + size_t vl) { + return __riscv_vrgather_vv_bf16m1(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m1( +// CHECK-RV64-SAME: [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv4bf16.i64( poison, [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vx_bf16m1(vbfloat16m1_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_vx_bf16m1(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m2( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv8bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vv_bf16m2(vbfloat16m2_t vs2, vuint16m2_t vs1, + size_t vl) { + return __riscv_vrgather_vv_bf16m2(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m2( +// CHECK-RV64-SAME: [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv8bf16.i64( poison, [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vx_bf16m2(vbfloat16m2_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_vx_bf16m2(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m4( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv16bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vv_bf16m4(vbfloat16m4_t vs2, vuint16m4_t vs1, + size_t vl) { + return __riscv_vrgather_vv_bf16m4(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m4( +// CHECK-RV64-SAME: [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv16bf16.i64( poison, [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vx_bf16m4(vbfloat16m4_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_vx_bf16m4(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m8( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv32bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vv_bf16m8(vbfloat16m8_t vs2, vuint16m8_t vs1, + size_t vl) { + return __riscv_vrgather_vv_bf16m8(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m8( +// CHECK-RV64-SAME: [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv32bf16.i64( poison, [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vx_bf16m8(vbfloat16m8_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_vx_bf16m8(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf4_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv1bf16.i64( poison, [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vv_bf16mf4_m(vbool64_t vm, vbfloat16mf4_t vs2, + vuint16mf4_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16mf4_m(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf4_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv1bf16.i64( poison, [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vx_bf16mf4_m(vbool64_t vm, vbfloat16mf4_t vs2, + size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16mf4_m(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf2_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv2bf16.i64( poison, [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vv_bf16mf2_m(vbool32_t vm, vbfloat16mf2_t vs2, + vuint16mf2_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16mf2_m(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf2_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv2bf16.i64( poison, [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vx_bf16mf2_m(vbool32_t vm, vbfloat16mf2_t vs2, + size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16mf2_m(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m1_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv4bf16.i64( poison, [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vv_bf16m1_m(vbool16_t vm, vbfloat16m1_t vs2, + vuint16m1_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16m1_m(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m1_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv4bf16.i64( poison, [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vx_bf16m1_m(vbool16_t vm, vbfloat16m1_t vs2, + size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16m1_m(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m2_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv8bf16.i64( poison, [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vv_bf16m2_m(vbool8_t vm, vbfloat16m2_t vs2, + vuint16m2_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16m2_m(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m2_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv8bf16.i64( poison, [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vx_bf16m2_m(vbool8_t vm, vbfloat16m2_t vs2, + size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16m2_m(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m4_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv16bf16.i64( poison, [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vv_bf16m4_m(vbool4_t vm, vbfloat16m4_t vs2, + vuint16m4_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16m4_m(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m4_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv16bf16.i64( poison, [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vx_bf16m4_m(vbool4_t vm, vbfloat16m4_t vs2, + size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16m4_m(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m8_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv32bf16.i64( poison, [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vv_bf16m8_m(vbool2_t vm, vbfloat16m8_t vs2, + vuint16m8_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16m8_m(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m8_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv32bf16.i64( poison, [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vx_bf16m8_m(vbool2_t vm, vbfloat16m8_t vs2, + size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16m8_m(vm, vs2, vs1, vl); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/overloaded/vcompress.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/overloaded/vcompress.c new file mode 100644 index 0000000000000..40de6fdccf95f --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/overloaded/vcompress.c @@ -0,0 +1,74 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +zve64x \ +// RUN: -target-feature +zvfbfmin -disable-O0-optnone \ +// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \ +// RUN: FileCheck --check-prefix=CHECK-RV64 %s + +#include + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16mf4( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv1bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vcompress_vm_bf16mf4(vbfloat16mf4_t vs2, vbool64_t vs1, + size_t vl) { + return __riscv_vcompress(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16mf2( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv2bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vcompress_vm_bf16mf2(vbfloat16mf2_t vs2, vbool32_t vs1, + size_t vl) { + return __riscv_vcompress(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16m1( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv4bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vcompress_vm_bf16m1(vbfloat16m1_t vs2, vbool16_t vs1, + size_t vl) { + return __riscv_vcompress(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16m2( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv8bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vcompress_vm_bf16m2(vbfloat16m2_t vs2, vbool8_t vs1, + size_t vl) { + return __riscv_vcompress(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16m4( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv16bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vcompress_vm_bf16m4(vbfloat16m4_t vs2, vbool4_t vs1, + size_t vl) { + return __riscv_vcompress(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16m8( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv32bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vcompress_vm_bf16m8(vbfloat16m8_t vs2, vbool2_t vs1, + size_t vl) { + return __riscv_vcompress(vs2, vs1, vl); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/overloaded/vrgather.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/overloaded/vrgather.c new file mode 100644 index 0000000000000..068d8498997b6 --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/overloaded/vrgather.c @@ -0,0 +1,272 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +zve64x \ +// RUN: -target-feature +zvfbfmin -disable-O0-optnone \ +// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \ +// RUN: FileCheck --check-prefix=CHECK-RV64 %s + +#include + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf4( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv1bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vv_bf16mf4(vbfloat16mf4_t vs2, vuint16mf4_t vs1, + size_t vl) { + return __riscv_vrgather(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf4( +// CHECK-RV64-SAME: [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv1bf16.i64( poison, [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vx_bf16mf4(vbfloat16mf4_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf2( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv2bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vv_bf16mf2(vbfloat16mf2_t vs2, vuint16mf2_t vs1, + size_t vl) { + return __riscv_vrgather(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf2( +// CHECK-RV64-SAME: [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv2bf16.i64( poison, [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vx_bf16mf2(vbfloat16mf2_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m1( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv4bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vv_bf16m1(vbfloat16m1_t vs2, vuint16m1_t vs1, + size_t vl) { + return __riscv_vrgather(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m1( +// CHECK-RV64-SAME: [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv4bf16.i64( poison, [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vx_bf16m1(vbfloat16m1_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m2( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv8bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vv_bf16m2(vbfloat16m2_t vs2, vuint16m2_t vs1, + size_t vl) { + return __riscv_vrgather(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m2( +// CHECK-RV64-SAME: [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv8bf16.i64( poison, [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vx_bf16m2(vbfloat16m2_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m4( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv16bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vv_bf16m4(vbfloat16m4_t vs2, vuint16m4_t vs1, + size_t vl) { + return __riscv_vrgather(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m4( +// CHECK-RV64-SAME: [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv16bf16.i64( poison, [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vx_bf16m4(vbfloat16m4_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m8( +// CHECK-RV64-SAME: [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv32bf16.i64( poison, [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vv_bf16m8(vbfloat16m8_t vs2, vuint16m8_t vs1, + size_t vl) { + return __riscv_vrgather(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m8( +// CHECK-RV64-SAME: [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv32bf16.i64( poison, [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vx_bf16m8(vbfloat16m8_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather(vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf4_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv1bf16.i64( poison, [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vv_bf16mf4_m(vbool64_t vm, vbfloat16mf4_t vs2, + vuint16mf4_t vs1, size_t vl) { + return __riscv_vrgather(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf4_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv1bf16.i64( poison, [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vx_bf16mf4_m(vbool64_t vm, vbfloat16mf4_t vs2, + size_t vs1, size_t vl) { + return __riscv_vrgather(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf2_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv2bf16.i64( poison, [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vv_bf16mf2_m(vbool32_t vm, vbfloat16mf2_t vs2, + vuint16mf2_t vs1, size_t vl) { + return __riscv_vrgather(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf2_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv2bf16.i64( poison, [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vx_bf16mf2_m(vbool32_t vm, vbfloat16mf2_t vs2, + size_t vs1, size_t vl) { + return __riscv_vrgather(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m1_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv4bf16.i64( poison, [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vv_bf16m1_m(vbool16_t vm, vbfloat16m1_t vs2, + vuint16m1_t vs1, size_t vl) { + return __riscv_vrgather(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m1_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv4bf16.i64( poison, [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vx_bf16m1_m(vbool16_t vm, vbfloat16m1_t vs2, + size_t vs1, size_t vl) { + return __riscv_vrgather(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m2_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv8bf16.i64( poison, [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vv_bf16m2_m(vbool8_t vm, vbfloat16m2_t vs2, + vuint16m2_t vs1, size_t vl) { + return __riscv_vrgather(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m2_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv8bf16.i64( poison, [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vx_bf16m2_m(vbool8_t vm, vbfloat16m2_t vs2, + size_t vs1, size_t vl) { + return __riscv_vrgather(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m4_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv16bf16.i64( poison, [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vv_bf16m4_m(vbool4_t vm, vbfloat16m4_t vs2, + vuint16m4_t vs1, size_t vl) { + return __riscv_vrgather(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m4_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv16bf16.i64( poison, [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vx_bf16m4_m(vbool4_t vm, vbfloat16m4_t vs2, + size_t vs1, size_t vl) { + return __riscv_vrgather(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m8_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv32bf16.i64( poison, [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vv_bf16m8_m(vbool2_t vm, vbfloat16m8_t vs2, + vuint16m8_t vs1, size_t vl) { + return __riscv_vrgather(vm, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m8_m( +// CHECK-RV64-SAME: [[VM:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv32bf16.i64( poison, [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 3) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vx_bf16m8_m(vbool2_t vm, vbfloat16m8_t vs2, + size_t vs1, size_t vl) { + return __riscv_vrgather(vm, vs2, vs1, vl); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/non-overloaded/vcompress.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/non-overloaded/vcompress.c new file mode 100644 index 0000000000000..90160c8fe19c3 --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/non-overloaded/vcompress.c @@ -0,0 +1,68 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +zve64x \ +// RUN: -target-feature +zvfbfmin -disable-O0-optnone \ +// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \ +// RUN: FileCheck --check-prefix=CHECK-RV64 %s + +#include + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16mf4_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv1bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vcompress_vm_bf16mf4_tu(vbfloat16mf4_t vd, vbfloat16mf4_t vs2, vbool64_t vs1, size_t vl) { + return __riscv_vcompress_vm_bf16mf4_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16mf2_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv2bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vcompress_vm_bf16mf2_tu(vbfloat16mf2_t vd, vbfloat16mf2_t vs2, vbool32_t vs1, size_t vl) { + return __riscv_vcompress_vm_bf16mf2_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16m1_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv4bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vcompress_vm_bf16m1_tu(vbfloat16m1_t vd, vbfloat16m1_t vs2, vbool16_t vs1, size_t vl) { + return __riscv_vcompress_vm_bf16m1_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16m2_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv8bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vcompress_vm_bf16m2_tu(vbfloat16m2_t vd, vbfloat16m2_t vs2, vbool8_t vs1, size_t vl) { + return __riscv_vcompress_vm_bf16m2_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16m4_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv16bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vcompress_vm_bf16m4_tu(vbfloat16m4_t vd, vbfloat16m4_t vs2, vbool4_t vs1, size_t vl) { + return __riscv_vcompress_vm_bf16m4_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16m8_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv32bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vcompress_vm_bf16m8_tu(vbfloat16m8_t vd, vbfloat16m8_t vs2, vbool2_t vs1, size_t vl) { + return __riscv_vcompress_vm_bf16m8_tu(vd, vs2, vs1, vl); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/non-overloaded/vrgather.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/non-overloaded/vrgather.c new file mode 100644 index 0000000000000..137ab17c190b9 --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/non-overloaded/vrgather.c @@ -0,0 +1,488 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +zve64x \ +// RUN: -target-feature +zvfbfmin -disable-O0-optnone \ +// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \ +// RUN: FileCheck --check-prefix=CHECK-RV64 %s + +#include + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf4_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv1bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vv_bf16mf4_tu(vbfloat16mf4_t vd, vbfloat16mf4_t vs2, vuint16mf4_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16mf4_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf4_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv1bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vx_bf16mf4_tu(vbfloat16mf4_t vd, vbfloat16mf4_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16mf4_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf2_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv2bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vv_bf16mf2_tu(vbfloat16mf2_t vd, vbfloat16mf2_t vs2, vuint16mf2_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16mf2_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf2_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv2bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vx_bf16mf2_tu(vbfloat16mf2_t vd, vbfloat16mf2_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16mf2_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m1_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv4bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vv_bf16m1_tu(vbfloat16m1_t vd, vbfloat16m1_t vs2, vuint16m1_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16m1_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m1_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv4bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vx_bf16m1_tu(vbfloat16m1_t vd, vbfloat16m1_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16m1_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m2_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv8bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vv_bf16m2_tu(vbfloat16m2_t vd, vbfloat16m2_t vs2, vuint16m2_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16m2_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m2_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv8bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vx_bf16m2_tu(vbfloat16m2_t vd, vbfloat16m2_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16m2_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m4_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv16bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vv_bf16m4_tu(vbfloat16m4_t vd, vbfloat16m4_t vs2, vuint16m4_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16m4_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m4_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv16bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vx_bf16m4_tu(vbfloat16m4_t vd, vbfloat16m4_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16m4_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m8_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv32bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vv_bf16m8_tu(vbfloat16m8_t vd, vbfloat16m8_t vs2, vuint16m8_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16m8_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m8_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv32bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vx_bf16m8_tu(vbfloat16m8_t vd, vbfloat16m8_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16m8_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf4_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv1bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vv_bf16mf4_tum(vbool64_t vm, vbfloat16mf4_t vd, vbfloat16mf4_t vs2, vuint16mf4_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16mf4_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf4_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv1bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vx_bf16mf4_tum(vbool64_t vm, vbfloat16mf4_t vd, vbfloat16mf4_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16mf4_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf2_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv2bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vv_bf16mf2_tum(vbool32_t vm, vbfloat16mf2_t vd, vbfloat16mf2_t vs2, vuint16mf2_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16mf2_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf2_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv2bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vx_bf16mf2_tum(vbool32_t vm, vbfloat16mf2_t vd, vbfloat16mf2_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16mf2_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m1_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv4bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vv_bf16m1_tum(vbool16_t vm, vbfloat16m1_t vd, vbfloat16m1_t vs2, vuint16m1_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16m1_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m1_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv4bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vx_bf16m1_tum(vbool16_t vm, vbfloat16m1_t vd, vbfloat16m1_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16m1_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m2_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv8bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vv_bf16m2_tum(vbool8_t vm, vbfloat16m2_t vd, vbfloat16m2_t vs2, vuint16m2_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16m2_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m2_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv8bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vx_bf16m2_tum(vbool8_t vm, vbfloat16m2_t vd, vbfloat16m2_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16m2_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m4_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv16bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vv_bf16m4_tum(vbool4_t vm, vbfloat16m4_t vd, vbfloat16m4_t vs2, vuint16m4_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16m4_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m4_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv16bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vx_bf16m4_tum(vbool4_t vm, vbfloat16m4_t vd, vbfloat16m4_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16m4_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m8_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv32bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vv_bf16m8_tum(vbool2_t vm, vbfloat16m8_t vd, vbfloat16m8_t vs2, vuint16m8_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16m8_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m8_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv32bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vx_bf16m8_tum(vbool2_t vm, vbfloat16m8_t vd, vbfloat16m8_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16m8_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf4_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv1bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vv_bf16mf4_tumu(vbool64_t vm, vbfloat16mf4_t vd, vbfloat16mf4_t vs2, vuint16mf4_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16mf4_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf4_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv1bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vx_bf16mf4_tumu(vbool64_t vm, vbfloat16mf4_t vd, vbfloat16mf4_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16mf4_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf2_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv2bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vv_bf16mf2_tumu(vbool32_t vm, vbfloat16mf2_t vd, vbfloat16mf2_t vs2, vuint16mf2_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16mf2_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf2_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv2bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vx_bf16mf2_tumu(vbool32_t vm, vbfloat16mf2_t vd, vbfloat16mf2_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16mf2_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m1_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv4bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vv_bf16m1_tumu(vbool16_t vm, vbfloat16m1_t vd, vbfloat16m1_t vs2, vuint16m1_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16m1_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m1_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv4bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vx_bf16m1_tumu(vbool16_t vm, vbfloat16m1_t vd, vbfloat16m1_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16m1_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m2_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv8bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vv_bf16m2_tumu(vbool8_t vm, vbfloat16m2_t vd, vbfloat16m2_t vs2, vuint16m2_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16m2_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m2_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv8bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vx_bf16m2_tumu(vbool8_t vm, vbfloat16m2_t vd, vbfloat16m2_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16m2_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m4_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv16bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vv_bf16m4_tumu(vbool4_t vm, vbfloat16m4_t vd, vbfloat16m4_t vs2, vuint16m4_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16m4_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m4_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv16bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vx_bf16m4_tumu(vbool4_t vm, vbfloat16m4_t vd, vbfloat16m4_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16m4_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m8_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv32bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vv_bf16m8_tumu(vbool2_t vm, vbfloat16m8_t vd, vbfloat16m8_t vs2, vuint16m8_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16m8_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m8_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv32bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vx_bf16m8_tumu(vbool2_t vm, vbfloat16m8_t vd, vbfloat16m8_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16m8_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf4_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv1bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vv_bf16mf4_mu(vbool64_t vm, vbfloat16mf4_t vd, vbfloat16mf4_t vs2, vuint16mf4_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16mf4_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf4_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv1bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vx_bf16mf4_mu(vbool64_t vm, vbfloat16mf4_t vd, vbfloat16mf4_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16mf4_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf2_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv2bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vv_bf16mf2_mu(vbool32_t vm, vbfloat16mf2_t vd, vbfloat16mf2_t vs2, vuint16mf2_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16mf2_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf2_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv2bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vx_bf16mf2_mu(vbool32_t vm, vbfloat16mf2_t vd, vbfloat16mf2_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16mf2_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m1_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv4bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vv_bf16m1_mu(vbool16_t vm, vbfloat16m1_t vd, vbfloat16m1_t vs2, vuint16m1_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16m1_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m1_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv4bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vx_bf16m1_mu(vbool16_t vm, vbfloat16m1_t vd, vbfloat16m1_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16m1_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m2_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv8bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vv_bf16m2_mu(vbool8_t vm, vbfloat16m2_t vd, vbfloat16m2_t vs2, vuint16m2_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16m2_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m2_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv8bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vx_bf16m2_mu(vbool8_t vm, vbfloat16m2_t vd, vbfloat16m2_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16m2_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m4_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv16bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vv_bf16m4_mu(vbool4_t vm, vbfloat16m4_t vd, vbfloat16m4_t vs2, vuint16m4_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16m4_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m4_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv16bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vx_bf16m4_mu(vbool4_t vm, vbfloat16m4_t vd, vbfloat16m4_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16m4_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m8_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv32bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vv_bf16m8_mu(vbool2_t vm, vbfloat16m8_t vd, vbfloat16m8_t vs2, vuint16m8_t vs1, size_t vl) { + return __riscv_vrgather_vv_bf16m8_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m8_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv32bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vx_bf16m8_mu(vbool2_t vm, vbfloat16m8_t vd, vbfloat16m8_t vs2, size_t vs1, size_t vl) { + return __riscv_vrgather_vx_bf16m8_mu(vm, vd, vs2, vs1, vl); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/overloaded/vcompress.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/overloaded/vcompress.c new file mode 100644 index 0000000000000..079977a0a06b0 --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/overloaded/vcompress.c @@ -0,0 +1,76 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +zve64x \ +// RUN: -target-feature +zvfbfmin -disable-O0-optnone \ +// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \ +// RUN: FileCheck --check-prefix=CHECK-RV64 %s + +#include + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16mf4_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv1bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vcompress_vm_bf16mf4_tu(vbfloat16mf4_t vd, + vbfloat16mf4_t vs2, vbool64_t vs1, + size_t vl) { + return __riscv_vcompress_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16mf2_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv2bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vcompress_vm_bf16mf2_tu(vbfloat16mf2_t vd, + vbfloat16mf2_t vs2, vbool32_t vs1, + size_t vl) { + return __riscv_vcompress_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16m1_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv4bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vcompress_vm_bf16m1_tu(vbfloat16m1_t vd, vbfloat16m1_t vs2, + vbool16_t vs1, size_t vl) { + return __riscv_vcompress_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16m2_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv8bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vcompress_vm_bf16m2_tu(vbfloat16m2_t vd, vbfloat16m2_t vs2, + vbool8_t vs1, size_t vl) { + return __riscv_vcompress_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16m4_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv16bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vcompress_vm_bf16m4_tu(vbfloat16m4_t vd, vbfloat16m4_t vs2, + vbool4_t vs1, size_t vl) { + return __riscv_vcompress_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vcompress_vm_bf16m8_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vcompress.nxv32bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vcompress_vm_bf16m8_tu(vbfloat16m8_t vd, vbfloat16m8_t vs2, + vbool2_t vs1, size_t vl) { + return __riscv_vcompress_tu(vd, vs2, vs1, vl); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/overloaded/vrgather.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/overloaded/vrgather.c new file mode 100644 index 0000000000000..7a5624aed608b --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/overloaded/vrgather.c @@ -0,0 +1,576 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +zve64x \ +// RUN: -target-feature +zvfbfmin -disable-O0-optnone \ +// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \ +// RUN: FileCheck --check-prefix=CHECK-RV64 %s + +#include + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf4_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv1bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vv_bf16mf4_tu(vbfloat16mf4_t vd, + vbfloat16mf4_t vs2, vuint16mf4_t vs1, + size_t vl) { + return __riscv_vrgather_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf4_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv1bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vx_bf16mf4_tu(vbfloat16mf4_t vd, + vbfloat16mf4_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf2_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv2bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vv_bf16mf2_tu(vbfloat16mf2_t vd, + vbfloat16mf2_t vs2, vuint16mf2_t vs1, + size_t vl) { + return __riscv_vrgather_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf2_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv2bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vx_bf16mf2_tu(vbfloat16mf2_t vd, + vbfloat16mf2_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m1_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv4bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vv_bf16m1_tu(vbfloat16m1_t vd, vbfloat16m1_t vs2, + vuint16m1_t vs1, size_t vl) { + return __riscv_vrgather_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m1_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv4bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vx_bf16m1_tu(vbfloat16m1_t vd, vbfloat16m1_t vs2, + size_t vs1, size_t vl) { + return __riscv_vrgather_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m2_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv8bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vv_bf16m2_tu(vbfloat16m2_t vd, vbfloat16m2_t vs2, + vuint16m2_t vs1, size_t vl) { + return __riscv_vrgather_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m2_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv8bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vx_bf16m2_tu(vbfloat16m2_t vd, vbfloat16m2_t vs2, + size_t vs1, size_t vl) { + return __riscv_vrgather_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m4_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv16bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vv_bf16m4_tu(vbfloat16m4_t vd, vbfloat16m4_t vs2, + vuint16m4_t vs1, size_t vl) { + return __riscv_vrgather_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m4_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv16bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vx_bf16m4_tu(vbfloat16m4_t vd, vbfloat16m4_t vs2, + size_t vs1, size_t vl) { + return __riscv_vrgather_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m8_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.nxv32bf16.i64( [[VD]], [[VS2]], [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vv_bf16m8_tu(vbfloat16m8_t vd, vbfloat16m8_t vs2, + vuint16m8_t vs1, size_t vl) { + return __riscv_vrgather_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m8_tu( +// CHECK-RV64-SAME: [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.nxv32bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], i64 [[VL]]) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vx_bf16m8_tu(vbfloat16m8_t vd, vbfloat16m8_t vs2, + size_t vs1, size_t vl) { + return __riscv_vrgather_tu(vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf4_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv1bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vv_bf16mf4_tum(vbool64_t vm, vbfloat16mf4_t vd, + vbfloat16mf4_t vs2, + vuint16mf4_t vs1, size_t vl) { + return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf4_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv1bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vx_bf16mf4_tum(vbool64_t vm, vbfloat16mf4_t vd, + vbfloat16mf4_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf2_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv2bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vv_bf16mf2_tum(vbool32_t vm, vbfloat16mf2_t vd, + vbfloat16mf2_t vs2, + vuint16mf2_t vs1, size_t vl) { + return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf2_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv2bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vx_bf16mf2_tum(vbool32_t vm, vbfloat16mf2_t vd, + vbfloat16mf2_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m1_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv4bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vv_bf16m1_tum(vbool16_t vm, vbfloat16m1_t vd, + vbfloat16m1_t vs2, vuint16m1_t vs1, + size_t vl) { + return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m1_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv4bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vx_bf16m1_tum(vbool16_t vm, vbfloat16m1_t vd, + vbfloat16m1_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m2_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv8bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vv_bf16m2_tum(vbool8_t vm, vbfloat16m2_t vd, + vbfloat16m2_t vs2, vuint16m2_t vs1, + size_t vl) { + return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m2_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv8bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vx_bf16m2_tum(vbool8_t vm, vbfloat16m2_t vd, + vbfloat16m2_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m4_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv16bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vv_bf16m4_tum(vbool4_t vm, vbfloat16m4_t vd, + vbfloat16m4_t vs2, vuint16m4_t vs1, + size_t vl) { + return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m4_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv16bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vx_bf16m4_tum(vbool4_t vm, vbfloat16m4_t vd, + vbfloat16m4_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m8_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv32bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vv_bf16m8_tum(vbool2_t vm, vbfloat16m8_t vd, + vbfloat16m8_t vs2, vuint16m8_t vs1, + size_t vl) { + return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m8_tum( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv32bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 2) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vx_bf16m8_tum(vbool2_t vm, vbfloat16m8_t vd, + vbfloat16m8_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf4_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv1bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vv_bf16mf4_tumu(vbool64_t vm, vbfloat16mf4_t vd, + vbfloat16mf4_t vs2, + vuint16mf4_t vs1, size_t vl) { + return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf4_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv1bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vx_bf16mf4_tumu(vbool64_t vm, vbfloat16mf4_t vd, + vbfloat16mf4_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf2_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv2bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vv_bf16mf2_tumu(vbool32_t vm, vbfloat16mf2_t vd, + vbfloat16mf2_t vs2, + vuint16mf2_t vs1, size_t vl) { + return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf2_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv2bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vx_bf16mf2_tumu(vbool32_t vm, vbfloat16mf2_t vd, + vbfloat16mf2_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m1_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv4bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vv_bf16m1_tumu(vbool16_t vm, vbfloat16m1_t vd, + vbfloat16m1_t vs2, vuint16m1_t vs1, + size_t vl) { + return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m1_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv4bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vx_bf16m1_tumu(vbool16_t vm, vbfloat16m1_t vd, + vbfloat16m1_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m2_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv8bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vv_bf16m2_tumu(vbool8_t vm, vbfloat16m2_t vd, + vbfloat16m2_t vs2, vuint16m2_t vs1, + size_t vl) { + return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m2_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv8bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vx_bf16m2_tumu(vbool8_t vm, vbfloat16m2_t vd, + vbfloat16m2_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m4_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv16bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vv_bf16m4_tumu(vbool4_t vm, vbfloat16m4_t vd, + vbfloat16m4_t vs2, vuint16m4_t vs1, + size_t vl) { + return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m4_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv16bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vx_bf16m4_tumu(vbool4_t vm, vbfloat16m4_t vd, + vbfloat16m4_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m8_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv32bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vv_bf16m8_tumu(vbool2_t vm, vbfloat16m8_t vd, + vbfloat16m8_t vs2, vuint16m8_t vs1, + size_t vl) { + return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m8_tumu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv32bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vx_bf16m8_tumu(vbool2_t vm, vbfloat16m8_t vd, + vbfloat16m8_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf4_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv1bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vv_bf16mf4_mu(vbool64_t vm, vbfloat16mf4_t vd, + vbfloat16mf4_t vs2, vuint16mf4_t vs1, + size_t vl) { + return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf4_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv1bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf4_t test_vrgather_vx_bf16mf4_mu(vbool64_t vm, vbfloat16mf4_t vd, + vbfloat16mf4_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16mf2_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv2bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vv_bf16mf2_mu(vbool32_t vm, vbfloat16mf2_t vd, + vbfloat16mf2_t vs2, vuint16mf2_t vs1, + size_t vl) { + return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16mf2_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv2bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16mf2_t test_vrgather_vx_bf16mf2_mu(vbool32_t vm, vbfloat16mf2_t vd, + vbfloat16mf2_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m1_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv4bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vv_bf16m1_mu(vbool16_t vm, vbfloat16m1_t vd, + vbfloat16m1_t vs2, vuint16m1_t vs1, + size_t vl) { + return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m1_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv4bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m1_t test_vrgather_vx_bf16m1_mu(vbool16_t vm, vbfloat16m1_t vd, + vbfloat16m1_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m2_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv8bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vv_bf16m2_mu(vbool8_t vm, vbfloat16m2_t vd, + vbfloat16m2_t vs2, vuint16m2_t vs1, + size_t vl) { + return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m2_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv8bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m2_t test_vrgather_vx_bf16m2_mu(vbool8_t vm, vbfloat16m2_t vd, + vbfloat16m2_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m4_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv16bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vv_bf16m4_mu(vbool4_t vm, vbfloat16m4_t vd, + vbfloat16m4_t vs2, vuint16m4_t vs1, + size_t vl) { + return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m4_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv16bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m4_t test_vrgather_vx_bf16m4_mu(vbool4_t vm, vbfloat16m4_t vd, + vbfloat16m4_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vv_bf16m8_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vv.mask.nxv32bf16.i64( [[VD]], [[VS2]], [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vv_bf16m8_mu(vbool2_t vm, vbfloat16m8_t vd, + vbfloat16m8_t vs2, vuint16m8_t vs1, + size_t vl) { + return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl); +} + +// CHECK-RV64-LABEL: define dso_local @test_vrgather_vx_bf16m8_mu( +// CHECK-RV64-SAME: [[VM:%.*]], [[VD:%.*]], [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] { +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vrgather.vx.mask.nxv32bf16.i64( [[VD]], [[VS2]], i64 [[VS1]], [[VM]], i64 [[VL]], i64 1) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vbfloat16m8_t test_vrgather_vx_bf16m8_mu(vbool2_t vm, vbfloat16m8_t vd, + vbfloat16m8_t vs2, size_t vs1, + size_t vl) { + return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl); +} diff --git a/clang/test/CodeGen/SystemZ/systemz-abi-vector.c b/clang/test/CodeGen/SystemZ/systemz-abi-vector.c index e5704709a3a33..fab6050a0d876 100644 --- a/clang/test/CodeGen/SystemZ/systemz-abi-vector.c +++ b/clang/test/CodeGen/SystemZ/systemz-abi-vector.c @@ -58,91 +58,91 @@ unsigned int align = __alignof__ (v16i8); // CHECK-VECTOR: @align ={{.*}} global i32 8 v1i8 pass_v1i8(v1i8 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v1i8(ptr dead_on_unwind noalias writable sret(<1 x i8>) align 1 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v1i8(ptr dead_on_unwind noalias writable sret(<1 x i8>) align 1 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <1 x i8> @pass_v1i8(<1 x i8> %{{.*}}) v2i8 pass_v2i8(v2i8 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v2i8(ptr dead_on_unwind noalias writable sret(<2 x i8>) align 2 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v2i8(ptr dead_on_unwind noalias writable sret(<2 x i8>) align 2 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <2 x i8> @pass_v2i8(<2 x i8> %{{.*}}) v4i8 pass_v4i8(v4i8 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v4i8(ptr dead_on_unwind noalias writable sret(<4 x i8>) align 4 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v4i8(ptr dead_on_unwind noalias writable sret(<4 x i8>) align 4 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <4 x i8> @pass_v4i8(<4 x i8> %{{.*}}) v8i8 pass_v8i8(v8i8 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v8i8(ptr dead_on_unwind noalias writable sret(<8 x i8>) align 8 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v8i8(ptr dead_on_unwind noalias writable sret(<8 x i8>) align 8 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <8 x i8> @pass_v8i8(<8 x i8> %{{.*}}) v16i8 pass_v16i8(v16i8 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v16i8(ptr dead_on_unwind noalias writable sret(<16 x i8>) align 16 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v16i8(ptr dead_on_unwind noalias writable sret(<16 x i8>) align 16 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <16 x i8> @pass_v16i8(<16 x i8> %{{.*}}) v32i8 pass_v32i8(v32i8 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v32i8(ptr dead_on_unwind noalias writable sret(<32 x i8>) align 32 %{{.*}}, ptr %0) -// CHECK-VECTOR-LABEL: define{{.*}} void @pass_v32i8(ptr dead_on_unwind noalias writable sret(<32 x i8>) align 8 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v32i8(ptr dead_on_unwind noalias writable sret(<32 x i8>) align 32 %{{.*}}, ptr dead_on_return %0) +// CHECK-VECTOR-LABEL: define{{.*}} void @pass_v32i8(ptr dead_on_unwind noalias writable sret(<32 x i8>) align 8 %{{.*}}, ptr dead_on_return %0) v1i16 pass_v1i16(v1i16 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v1i16(ptr dead_on_unwind noalias writable sret(<1 x i16>) align 2 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v1i16(ptr dead_on_unwind noalias writable sret(<1 x i16>) align 2 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <1 x i16> @pass_v1i16(<1 x i16> %{{.*}}) v2i16 pass_v2i16(v2i16 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v2i16(ptr dead_on_unwind noalias writable sret(<2 x i16>) align 4 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v2i16(ptr dead_on_unwind noalias writable sret(<2 x i16>) align 4 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <2 x i16> @pass_v2i16(<2 x i16> %{{.*}}) v4i16 pass_v4i16(v4i16 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v4i16(ptr dead_on_unwind noalias writable sret(<4 x i16>) align 8 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v4i16(ptr dead_on_unwind noalias writable sret(<4 x i16>) align 8 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <4 x i16> @pass_v4i16(<4 x i16> %{{.*}}) v8i16 pass_v8i16(v8i16 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v8i16(ptr dead_on_unwind noalias writable sret(<8 x i16>) align 16 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v8i16(ptr dead_on_unwind noalias writable sret(<8 x i16>) align 16 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <8 x i16> @pass_v8i16(<8 x i16> %{{.*}}) v1i32 pass_v1i32(v1i32 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v1i32(ptr dead_on_unwind noalias writable sret(<1 x i32>) align 4 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v1i32(ptr dead_on_unwind noalias writable sret(<1 x i32>) align 4 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <1 x i32> @pass_v1i32(<1 x i32> %{{.*}}) v2i32 pass_v2i32(v2i32 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v2i32(ptr dead_on_unwind noalias writable sret(<2 x i32>) align 8 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v2i32(ptr dead_on_unwind noalias writable sret(<2 x i32>) align 8 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <2 x i32> @pass_v2i32(<2 x i32> %{{.*}}) v4i32 pass_v4i32(v4i32 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v4i32(ptr dead_on_unwind noalias writable sret(<4 x i32>) align 16 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v4i32(ptr dead_on_unwind noalias writable sret(<4 x i32>) align 16 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <4 x i32> @pass_v4i32(<4 x i32> %{{.*}}) v1i64 pass_v1i64(v1i64 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v1i64(ptr dead_on_unwind noalias writable sret(<1 x i64>) align 8 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v1i64(ptr dead_on_unwind noalias writable sret(<1 x i64>) align 8 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <1 x i64> @pass_v1i64(<1 x i64> %{{.*}}) v2i64 pass_v2i64(v2i64 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v2i64(ptr dead_on_unwind noalias writable sret(<2 x i64>) align 16 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v2i64(ptr dead_on_unwind noalias writable sret(<2 x i64>) align 16 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <2 x i64> @pass_v2i64(<2 x i64> %{{.*}}) v1i128 pass_v1i128(v1i128 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v1i128(ptr dead_on_unwind noalias writable sret(<1 x i128>) align 16 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v1i128(ptr dead_on_unwind noalias writable sret(<1 x i128>) align 16 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <1 x i128> @pass_v1i128(<1 x i128> %{{.*}}) v1f32 pass_v1f32(v1f32 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v1f32(ptr dead_on_unwind noalias writable sret(<1 x float>) align 4 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v1f32(ptr dead_on_unwind noalias writable sret(<1 x float>) align 4 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <1 x float> @pass_v1f32(<1 x float> %{{.*}}) v2f32 pass_v2f32(v2f32 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v2f32(ptr dead_on_unwind noalias writable sret(<2 x float>) align 8 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v2f32(ptr dead_on_unwind noalias writable sret(<2 x float>) align 8 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <2 x float> @pass_v2f32(<2 x float> %{{.*}}) v4f32 pass_v4f32(v4f32 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v4f32(ptr dead_on_unwind noalias writable sret(<4 x float>) align 16 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v4f32(ptr dead_on_unwind noalias writable sret(<4 x float>) align 16 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <4 x float> @pass_v4f32(<4 x float> %{{.*}}) v1f64 pass_v1f64(v1f64 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v1f64(ptr dead_on_unwind noalias writable sret(<1 x double>) align 8 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v1f64(ptr dead_on_unwind noalias writable sret(<1 x double>) align 8 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <1 x double> @pass_v1f64(<1 x double> %{{.*}}) v2f64 pass_v2f64(v2f64 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v2f64(ptr dead_on_unwind noalias writable sret(<2 x double>) align 16 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v2f64(ptr dead_on_unwind noalias writable sret(<2 x double>) align 16 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <2 x double> @pass_v2f64(<2 x double> %{{.*}}) v1f128 pass_v1f128(v1f128 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v1f128(ptr dead_on_unwind noalias writable sret(<1 x fp128>) align 16 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v1f128(ptr dead_on_unwind noalias writable sret(<1 x fp128>) align 16 %{{.*}}, ptr dead_on_return %0) // CHECK-VECTOR-LABEL: define{{.*}} <1 x fp128> @pass_v1f128(<1 x fp128> %{{.*}}) @@ -170,13 +170,13 @@ struct agg_v8i8 pass_agg_v8i8(struct agg_v8i8 arg) { return arg; } struct agg_v16i8 { v16i8 a; }; struct agg_v16i8 pass_agg_v16i8(struct agg_v16i8 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_v16i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v16i8) align 16 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_v16i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v16i8) align 16 %{{.*}}, ptr dead_on_return %{{.*}}) // CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_v16i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v16i8) align 8 %{{.*}}, <16 x i8> %{{.*}}) struct agg_v32i8 { v32i8 a; }; struct agg_v32i8 pass_agg_v32i8(struct agg_v32i8 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_v32i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v32i8) align 32 %{{.*}}, ptr %{{.*}}) -// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_v32i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v32i8) align 8 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_v32i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v32i8) align 32 %{{.*}}, ptr dead_on_return %{{.*}}) +// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_v32i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v32i8) align 8 %{{.*}}, ptr dead_on_return %{{.*}}) // Verify that the following are *not* vector-like aggregate types diff --git a/clang/test/CodeGen/SystemZ/systemz-abi.c b/clang/test/CodeGen/SystemZ/systemz-abi.c index f26084ab44eae..83137ae6d5f82 100644 --- a/clang/test/CodeGen/SystemZ/systemz-abi.c +++ b/clang/test/CodeGen/SystemZ/systemz-abi.c @@ -50,7 +50,7 @@ long long pass_longlong(long long arg) { return arg; } // CHECK-LABEL: define{{.*}} i64 @pass_longlong(i64 %{{.*}}) __int128 pass_int128(__int128 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_int128(ptr dead_on_unwind noalias writable sret(i128) align 8 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_int128(ptr dead_on_unwind noalias writable sret(i128) align 8 %{{.*}}, ptr dead_on_return %0) _Float16 pass__Float16(_Float16 arg) { return arg; } // CHECK-LABEL: define{{.*}} half @pass__Float16(half %{{.*}}) @@ -62,37 +62,37 @@ double pass_double(double arg) { return arg; } // CHECK-LABEL: define{{.*}} double @pass_double(double %{{.*}}) long double pass_longdouble(long double arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_longdouble(ptr dead_on_unwind noalias writable sret(fp128) align 8 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_longdouble(ptr dead_on_unwind noalias writable sret(fp128) align 8 %{{.*}}, ptr dead_on_return %0) // Complex types _Complex char pass_complex_char(_Complex char arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_complex_char(ptr dead_on_unwind noalias writable sret({ i8, i8 }) align 1 %{{.*}}, ptr %{{.*}}arg) +// CHECK-LABEL: define{{.*}} void @pass_complex_char(ptr dead_on_unwind noalias writable sret({ i8, i8 }) align 1 %{{.*}}, ptr dead_on_return %{{.*}}arg) _Complex short pass_complex_short(_Complex short arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_complex_short(ptr dead_on_unwind noalias writable sret({ i16, i16 }) align 2 %{{.*}}, ptr %{{.*}}arg) +// CHECK-LABEL: define{{.*}} void @pass_complex_short(ptr dead_on_unwind noalias writable sret({ i16, i16 }) align 2 %{{.*}}, ptr dead_on_return %{{.*}}arg) _Complex int pass_complex_int(_Complex int arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_complex_int(ptr dead_on_unwind noalias writable sret({ i32, i32 }) align 4 %{{.*}}, ptr %{{.*}}arg) +// CHECK-LABEL: define{{.*}} void @pass_complex_int(ptr dead_on_unwind noalias writable sret({ i32, i32 }) align 4 %{{.*}}, ptr dead_on_return %{{.*}}arg) _Complex long pass_complex_long(_Complex long arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_complex_long(ptr dead_on_unwind noalias writable sret({ i64, i64 }) align 8 %{{.*}}, ptr %{{.*}}arg) +// CHECK-LABEL: define{{.*}} void @pass_complex_long(ptr dead_on_unwind noalias writable sret({ i64, i64 }) align 8 %{{.*}}, ptr dead_on_return %{{.*}}arg) _Complex long long pass_complex_longlong(_Complex long long arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_complex_longlong(ptr dead_on_unwind noalias writable sret({ i64, i64 }) align 8 %{{.*}}, ptr %{{.*}}arg) +// CHECK-LABEL: define{{.*}} void @pass_complex_longlong(ptr dead_on_unwind noalias writable sret({ i64, i64 }) align 8 %{{.*}}, ptr dead_on_return %{{.*}}arg) _Complex _Float16 pass_complex__Float16(_Complex _Float16 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_complex__Float16(ptr dead_on_unwind noalias writable sret({ half, half }) align 2 %{{.*}}, ptr %{{.*}}arg) +// CHECK-LABEL: define{{.*}} void @pass_complex__Float16(ptr dead_on_unwind noalias writable sret({ half, half }) align 2 %{{.*}}, ptr dead_on_return %{{.*}}arg) _Complex float pass_complex_float(_Complex float arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_complex_float(ptr dead_on_unwind noalias writable sret({ float, float }) align 4 %{{.*}}, ptr %{{.*}}arg) +// CHECK-LABEL: define{{.*}} void @pass_complex_float(ptr dead_on_unwind noalias writable sret({ float, float }) align 4 %{{.*}}, ptr dead_on_return %{{.*}}arg) _Complex double pass_complex_double(_Complex double arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_complex_double(ptr dead_on_unwind noalias writable sret({ double, double }) align 8 %{{.*}}, ptr %{{.*}}arg) +// CHECK-LABEL: define{{.*}} void @pass_complex_double(ptr dead_on_unwind noalias writable sret({ double, double }) align 8 %{{.*}}, ptr dead_on_return %{{.*}}arg) _Complex long double pass_complex_longdouble(_Complex long double arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_complex_longdouble(ptr dead_on_unwind noalias writable sret({ fp128, fp128 }) align 8 %{{.*}}, ptr %{{.*}}arg) +// CHECK-LABEL: define{{.*}} void @pass_complex_longdouble(ptr dead_on_unwind noalias writable sret({ fp128, fp128 }) align 8 %{{.*}}, ptr dead_on_return %{{.*}}arg) // Aggregate types @@ -107,7 +107,7 @@ struct agg_2byte pass_agg_2byte(struct agg_2byte arg) { return arg; } struct agg_3byte { char a[3]; }; struct agg_3byte pass_agg_3byte(struct agg_3byte arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_3byte(ptr dead_on_unwind noalias writable sret(%struct.agg_3byte) align 1 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_3byte(ptr dead_on_unwind noalias writable sret(%struct.agg_3byte) align 1 %{{.*}}, ptr dead_on_return %{{.*}}) struct agg_4byte { char a[4]; }; struct agg_4byte pass_agg_4byte(struct agg_4byte arg) { return arg; } @@ -115,15 +115,15 @@ struct agg_4byte pass_agg_4byte(struct agg_4byte arg) { return arg; } struct agg_5byte { char a[5]; }; struct agg_5byte pass_agg_5byte(struct agg_5byte arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_5byte(ptr dead_on_unwind noalias writable sret(%struct.agg_5byte) align 1 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_5byte(ptr dead_on_unwind noalias writable sret(%struct.agg_5byte) align 1 %{{.*}}, ptr dead_on_return %{{.*}}) struct agg_6byte { char a[6]; }; struct agg_6byte pass_agg_6byte(struct agg_6byte arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_6byte(ptr dead_on_unwind noalias writable sret(%struct.agg_6byte) align 1 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_6byte(ptr dead_on_unwind noalias writable sret(%struct.agg_6byte) align 1 %{{.*}}, ptr dead_on_return %{{.*}}) struct agg_7byte { char a[7]; }; struct agg_7byte pass_agg_7byte(struct agg_7byte arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_7byte(ptr dead_on_unwind noalias writable sret(%struct.agg_7byte) align 1 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_7byte(ptr dead_on_unwind noalias writable sret(%struct.agg_7byte) align 1 %{{.*}}, ptr dead_on_return %{{.*}}) struct agg_8byte { char a[8]; }; struct agg_8byte pass_agg_8byte(struct agg_8byte arg) { return arg; } @@ -131,7 +131,7 @@ struct agg_8byte pass_agg_8byte(struct agg_8byte arg) { return arg; } struct agg_16byte { char a[16]; }; struct agg_16byte pass_agg_16byte(struct agg_16byte arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_16byte(ptr dead_on_unwind noalias writable sret(%struct.agg_16byte) align 1 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_16byte(ptr dead_on_unwind noalias writable sret(%struct.agg_16byte) align 1 %{{.*}}, ptr dead_on_return %{{.*}}) // Float-like aggregate types @@ -153,7 +153,7 @@ struct agg_double pass_agg_double(struct agg_double arg) { return arg; } struct agg_longdouble { long double a; }; struct agg_longdouble pass_agg_longdouble(struct agg_longdouble arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_longdouble(ptr dead_on_unwind noalias writable sret(%struct.agg_longdouble) align 8 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_longdouble(ptr dead_on_unwind noalias writable sret(%struct.agg_longdouble) align 8 %{{.*}}, ptr dead_on_return %{{.*}}) struct agg__Float16_a4 { _Float16 a __attribute__((aligned (4))); }; struct agg__Float16_a4 pass_agg__Float16_a4(struct agg__Float16_a4 arg) { return arg; } @@ -167,7 +167,7 @@ struct agg__Float16_a8 pass_agg__Float16_a8(struct agg__Float16_a8 arg) { return struct agg__Float16_a16 { _Float16 a __attribute__((aligned (16))); }; struct agg__Float16_a16 pass_agg__Float16_a16(struct agg__Float16_a16 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg__Float16_a16(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16_a16) align 16 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg__Float16_a16(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16_a16) align 16 %{{.*}}, ptr dead_on_return %{{.*}}) struct agg_float_a8 { float a __attribute__((aligned (8))); }; struct agg_float_a8 pass_agg_float_a8(struct agg_float_a8 arg) { return arg; } @@ -176,7 +176,7 @@ struct agg_float_a8 pass_agg_float_a8(struct agg_float_a8 arg) { return arg; } struct agg_float_a16 { float a __attribute__((aligned (16))); }; struct agg_float_a16 pass_agg_float_a16(struct agg_float_a16 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_float_a16(ptr dead_on_unwind noalias writable sret(%struct.agg_float_a16) align 16 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_float_a16(ptr dead_on_unwind noalias writable sret(%struct.agg_float_a16) align 16 %{{.*}}, ptr dead_on_return %{{.*}}) // Verify that the following are *not* float-like aggregate types diff --git a/clang/test/CodeGen/SystemZ/systemz-inline-asm.c b/clang/test/CodeGen/SystemZ/systemz-inline-asm.c index 434937a66389c..d76fb4bd1fda6 100644 --- a/clang/test/CodeGen/SystemZ/systemz-inline-asm.c +++ b/clang/test/CodeGen/SystemZ/systemz-inline-asm.c @@ -131,7 +131,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 writable writeonly sret(fp128) align 8 captures(none) initializes((0, 16)) [[DEST:%.*]], ptr noundef readonly captures(none) %0, ptr noundef readonly captures(none) %1) +// CHECK: define{{.*}} void @test_f128(ptr dead_on_unwind noalias writable writeonly sret(fp128) align 8 captures(none) initializes((0, 16)) [[DEST:%.*]], ptr dead_on_return noundef readonly captures(none) %0, ptr dead_on_return noundef readonly captures(none) %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/X86/cx-complex-range.c b/clang/test/CodeGen/X86/cx-complex-range.c index f87091427df71..b16b10b7b8a21 100644 --- a/clang/test/CodeGen/X86/cx-complex-range.c +++ b/clang/test/CodeGen/X86/cx-complex-range.c @@ -1064,7 +1064,7 @@ _Complex _Float16 mulf16(_Complex _Float16 a, _Complex _Float16 b) { // PRMTD-NEXT: ret <2 x half> [[TMP33]] // // X86WINPRMTD-LABEL: define dso_local i32 @f1( -// X86WINPRMTD-SAME: i32 noundef [[A_COERCE:%.*]], ptr noundef [[B:%.*]], i32 noundef [[C_COERCE:%.*]]) #[[ATTR0]] { +// X86WINPRMTD-SAME: i32 noundef [[A_COERCE:%.*]], ptr dead_on_return noundef [[B:%.*]], i32 noundef [[C_COERCE:%.*]]) #[[ATTR0]] { // X86WINPRMTD-NEXT: entry: // X86WINPRMTD-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 // X86WINPRMTD-NEXT: [[A:%.*]] = alloca { half, half }, align 2 diff --git a/clang/test/CodeGen/X86/i128-debuginfo.c b/clang/test/CodeGen/X86/i128-debuginfo.c new file mode 100644 index 0000000000000..4b865c1bed9f0 --- /dev/null +++ b/clang/test/CodeGen/X86/i128-debuginfo.c @@ -0,0 +1,10 @@ +// no autogeneration since update_cc_test_checks does not support -g +// RUN: %clang_cc1 -triple x86_64-pc-linux -O1 -debug-info-kind=limited -emit-llvm -o - %s | FileCheck %s + +// CHECK-LABEL: define{{.*}} i128 @add(i128 noundef %a) +// CHECK: #dbg_value(i128 %a, ![[DI:.*]], !DIExpression() +__int128_t add(__int128_t a) { + return a + a; +} + +// CHECK: ![[DI]] = !DILocalVariable(name: "a", arg: 1 diff --git a/clang/test/CodeGen/X86/prefetchi-error.c b/clang/test/CodeGen/X86/prefetchi-error.c new file mode 100644 index 0000000000000..31494f7cff152 --- /dev/null +++ b/clang/test/CodeGen/X86/prefetchi-error.c @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown -target-feature +prefetchi -fsyntax-only -verify + +#include + +void test_invalid_prefetchi(void* p) { + __builtin_ia32_prefetchi(p, 1); // expected-error {{argument value 1 is outside the valid range [2, 3]}} +} diff --git a/clang/test/CodeGen/X86/x86_32-arguments-win32.c b/clang/test/CodeGen/X86/x86_32-arguments-win32.c index 5b81c43f4bbb8..53d040af725b0 100644 --- a/clang/test/CodeGen/X86/x86_32-arguments-win32.c +++ b/clang/test/CodeGen/X86/x86_32-arguments-win32.c @@ -72,10 +72,10 @@ void receive_vec_512(__m512 x, __m512 y, __m512 z, __m512 w, __m512 q) { void receive_vec_1024(__m1024 x, __m1024 y, __m1024 z, __m1024 w, __m1024 q) { gv1024 = x + y + z + w + q; } -// CHECK-LABEL: define dso_local void @receive_vec_128(<4 x float> inreg noundef %x, <4 x float> inreg noundef %y, <4 x float> inreg noundef %z, ptr noundef %0, ptr noundef %1) -// CHECK-LABEL: define dso_local void @receive_vec_256(<8 x float> inreg noundef %x, <8 x float> inreg noundef %y, <8 x float> inreg noundef %z, ptr noundef %0, ptr noundef %1) -// CHECK-LABEL: define dso_local void @receive_vec_512(<16 x float> inreg noundef %x, <16 x float> inreg noundef %y, <16 x float> inreg noundef %z, ptr noundef %0, ptr noundef %1) -// CHECK-LABEL: define dso_local void @receive_vec_1024(ptr noundef %0, ptr noundef %1, ptr noundef %2, ptr noundef %3, ptr noundef %4) +// CHECK-LABEL: define dso_local void @receive_vec_128(<4 x float> inreg noundef %x, <4 x float> inreg noundef %y, <4 x float> inreg noundef %z, ptr dead_on_return noundef %0, ptr dead_on_return noundef %1) +// CHECK-LABEL: define dso_local void @receive_vec_256(<8 x float> inreg noundef %x, <8 x float> inreg noundef %y, <8 x float> inreg noundef %z, ptr dead_on_return noundef %0, ptr dead_on_return noundef %1) +// CHECK-LABEL: define dso_local void @receive_vec_512(<16 x float> inreg noundef %x, <16 x float> inreg noundef %y, <16 x float> inreg noundef %z, ptr dead_on_return noundef %0, ptr dead_on_return noundef %1) +// CHECK-LABEL: define dso_local void @receive_vec_1024(ptr dead_on_return noundef %0, ptr dead_on_return noundef %1, ptr dead_on_return noundef %2, ptr dead_on_return noundef %3, ptr dead_on_return noundef %4) void pass_vec_128(void) { __m128 z = {0}; @@ -83,13 +83,13 @@ void pass_vec_128(void) { } // CHECK-LABEL: define dso_local void @pass_vec_128() -// CHECK: call void @receive_vec_128(<4 x float> inreg noundef %{{[^,)]*}}, <4 x float> inreg noundef %{{[^,)]*}}, <4 x float> inreg noundef %{{[^,)]*}}, ptr noundef %{{[^,)]*}}, ptr noundef %{{[^,)]*}}) +// CHECK: call void @receive_vec_128(<4 x float> inreg noundef %{{[^,)]*}}, <4 x float> inreg noundef %{{[^,)]*}}, <4 x float> inreg noundef %{{[^,)]*}}, ptr dead_on_return noundef %{{[^,)]*}}, ptr dead_on_return noundef %{{[^,)]*}}) void __fastcall fastcall_indirect_vec(__m128 x, __m128 y, __m128 z, __m128 w, int edx, __m128 q) { gv128 = x + y + z + w + q; } -// CHECK-LABEL: define dso_local x86_fastcallcc void @"\01@fastcall_indirect_vec@84"(<4 x float> inreg noundef %x, <4 x float> inreg noundef %y, <4 x float> inreg noundef %z, ptr inreg noundef %0, i32 inreg noundef %edx, ptr noundef %1) +// CHECK-LABEL: define dso_local x86_fastcallcc void @"\01@fastcall_indirect_vec@84"(<4 x float> inreg noundef %x, <4 x float> inreg noundef %y, <4 x float> inreg noundef %z, ptr dead_on_return inreg noundef %0, i32 inreg noundef %edx, ptr dead_on_return noundef %1) struct __declspec(align(1)) Align1 { unsigned long long x; }; struct __declspec(align(4)) Align4 { unsigned long long x; }; @@ -156,4 +156,4 @@ void pass_fixed_align_variadic() { // correctly in Clang than it is to be bug for bug compatible, so we pass such // arguments indirectly. // CHECK-LABEL: define dso_local void @pass_fixed_align_variadic() -// CHECK: call void (ptr, ...) @receive_fixed_align_variadic(ptr noundef %{{[^)]*}}, i32 noundef 42) +// CHECK: call void (ptr, ...) @receive_fixed_align_variadic(ptr dead_on_return noundef %{{[^)]*}}, i32 noundef 42) diff --git a/clang/test/CodeGen/X86/x86_64-arguments-win32.c b/clang/test/CodeGen/X86/x86_64-arguments-win32.c index 8768e73a854aa..6010e531acb00 100644 --- a/clang/test/CodeGen/X86/x86_64-arguments-win32.c +++ b/clang/test/CodeGen/X86/x86_64-arguments-win32.c @@ -21,7 +21,7 @@ void f4(unsigned short a) {} // CHECK-LABEL: define dso_local void @f5(i64 noundef %a.coerce) void f5(_Complex float a) {} -// CHECK-LABEL: define dso_local void @f6(ptr noundef %a) +// CHECK-LABEL: define dso_local void @f6(ptr dead_on_return noundef %a) void f6(_Complex double a) {} // CHECK-LABEL: define dso_local i64 @f7() diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c b/clang/test/CodeGen/X86/x86_64-arguments.c index 82845f0a2b31f..580f9487395d3 100644 --- a/clang/test/CodeGen/X86/x86_64-arguments.c +++ b/clang/test/CodeGen/X86/x86_64-arguments.c @@ -551,6 +551,45 @@ struct s68 { void f68(struct s68 x) { } +// CHECK-LABEL: define{{.*}} i128 @f69(i128 noundef %a) +__int128_t f69(__int128_t a) { + return a; +} + +// CHECK-LABEL: define{{.*}} i128 @f70(i128 noundef %a) +__uint128_t f70(__uint128_t a) { + return a; +} + +// check that registers are correctly counted for (u)int128_t arguments +struct s71 { + long long a, b; +}; +// CHECK-LABEL: define{{.*}} void @f71(i128 noundef %a, i128 noundef %b, i64 noundef %c, ptr noundef byval(%struct.s71) align 8 %d) +void f71(__int128_t a, __int128_t b, long long c, struct s71 d) { +} +// CHECK-LABEL: define{{.*}} void @f72(i128 noundef %a, i128 noundef %b, i64 %d.coerce0, i64 %d.coerce1) +void f72(__int128_t a, __int128_t b, struct s71 d) { +} + +// check that structs containing (u)int128_t are passed correctly +struct s73 { + struct inner { + __uint128_t a; + }; + struct inner in; +}; +// CHECK-LABEL: define{{.*}} i128 @f73(i128 %a.coerce) +struct s73 f73(struct s73 a) { + return a; +} + +// check that _BitInt(128) is still passed correctly on the stack +// CHECK-LABEL: define{{.*}} i128 @f74(i128 noundef %b, i128 noundef %c, i128 noundef %d, i64 noundef %e, ptr noundef byval(i128) align 8 %0) +_BitInt(128) f74(__uint128_t b, __uint128_t c, __uint128_t d, long e, _BitInt(128) a) { + return a; +} + /// The synthesized __va_list_tag does not have file/line fields. // CHECK: = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "__va_list_tag", // CHECK-NOT: file: diff --git a/clang/test/CodeGen/aapcs64-align.cpp b/clang/test/CodeGen/aapcs64-align.cpp index 1c26d68e434f4..53fc53c2f7296 100644 --- a/clang/test/CodeGen/aapcs64-align.cpp +++ b/clang/test/CodeGen/aapcs64-align.cpp @@ -122,8 +122,8 @@ unsigned sizeof_RidiculouslyOverSizedBitfield = sizeof(RidiculouslyOverSizedBitf unsigned alignof_RidiculouslyOverSizedBitfield = alignof(RidiculouslyOverSizedBitfield); // CHECK: define{{.*}} void @g9 -// CHECK: call void @f9(i32 noundef 1, ptr noundef nonnull %agg.tmp) -// CHECK: declare void @f9(i32 noundef, ptr noundef) +// CHECK: call void @f9(i32 noundef 1, ptr dead_on_return noundef nonnull %agg.tmp) +// CHECK: declare void @f9(i32 noundef, ptr dead_on_return noundef) void f9(int a, RidiculouslyOverSizedBitfield b); void g9() { RidiculouslyOverSizedBitfield s = {42}; diff --git a/clang/test/CodeGen/alloc-align-attr.c b/clang/test/CodeGen/alloc-align-attr.c index 76e5d1041b19f..c4c4e76eaaa04 100644 --- a/clang/test/CodeGen/alloc-align-attr.c +++ b/clang/test/CodeGen/alloc-align-attr.c @@ -70,66 +70,42 @@ __INT32_TYPE__ test4(__SIZE_TYPE__ a) { struct Empty {}; struct MultiArgs { __INT64_TYPE__ a, b;}; -// Struct parameter doesn't take up an IR parameter, 'i' takes up 2. +// Struct parameter doesn't take up an IR parameter, 'i' takes up 1. // Truncation to i64 is permissible, since alignments of greater than 2^64 are insane. __INT32_TYPE__ *m3(struct Empty s, __int128_t i) __attribute__((alloc_align(2))); // CHECK-LABEL: @test5( // CHECK-NEXT: entry: -// CHECK-NEXT: [[A:%.*]] = alloca i128, align 16 // CHECK-NEXT: [[A_ADDR:%.*]] = alloca i128, align 16 // CHECK-NEXT: [[E:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1 -// CHECK-NEXT: [[COERCE:%.*]] = alloca i128, align 16 -// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[A]], i32 0, i32 0 -// CHECK-NEXT: store i64 [[A_COERCE0:%.*]], ptr [[TMP0]], align 16 -// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[A]], i32 0, i32 1 -// CHECK-NEXT: store i64 [[A_COERCE1:%.*]], ptr [[TMP1]], align 8 -// CHECK-NEXT: [[A1:%.*]] = load i128, ptr [[A]], align 16 -// CHECK-NEXT: store i128 [[A1]], ptr [[A_ADDR]], align 16 -// CHECK-NEXT: [[TMP2:%.*]] = load i128, ptr [[A_ADDR]], align 16 -// CHECK-NEXT: store i128 [[TMP2]], ptr [[COERCE]], align 16 -// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0 -// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 16 -// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1 -// CHECK-NEXT: [[TMP6:%.*]] = load i64, ptr [[TMP5]], align 8 -// CHECK-NEXT: [[CALL:%.*]] = call ptr @m3(i64 noundef [[TMP4]], i64 noundef [[TMP6]]) -// CHECK-NEXT: [[CASTED_ALIGN:%.*]] = trunc i128 [[TMP2]] to i64 +// CHECK-NEXT: store i128 [[A:%.*]], ptr [[A_ADDR]], align 16 +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr [[A_ADDR]], align 16 +// CHECK-NEXT: [[CALL:%.*]] = call ptr @m3(i128 noundef [[TMP0]]) +// CHECK-NEXT: [[CASTED_ALIGN:%.*]] = trunc i128 [[TMP0]] to i64 // CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[CALL]], i64 [[CASTED_ALIGN]]) ] -// CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[CALL]], align 4 -// CHECK-NEXT: ret i32 [[TMP7]] +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[CALL]], align 4 +// CHECK-NEXT: ret i32 [[TMP1]] // __INT32_TYPE__ test5(__int128_t a) { struct Empty e; return *m3(e, a); } -// Struct parameter takes up 2 parameters, 'i' takes up 2. +// Struct parameter takes up 2 parameters, 'i' takes up 1. __INT32_TYPE__ *m4(struct MultiArgs s, __int128_t i) __attribute__((alloc_align(2))); // CHECK-LABEL: @test6( // CHECK-NEXT: entry: -// CHECK-NEXT: [[A:%.*]] = alloca i128, align 16 // CHECK-NEXT: [[A_ADDR:%.*]] = alloca i128, align 16 // CHECK-NEXT: [[E:%.*]] = alloca [[STRUCT_MULTIARGS:%.*]], align 8 -// CHECK-NEXT: [[COERCE:%.*]] = alloca i128, align 16 -// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[A]], i32 0, i32 0 -// CHECK-NEXT: store i64 [[A_COERCE0:%.*]], ptr [[TMP0]], align 16 -// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[A]], i32 0, i32 1 -// CHECK-NEXT: store i64 [[A_COERCE1:%.*]], ptr [[TMP1]], align 8 -// CHECK-NEXT: [[A1:%.*]] = load i128, ptr [[A]], align 16 -// CHECK-NEXT: store i128 [[A1]], ptr [[A_ADDR]], align 16 -// CHECK-NEXT: [[TMP2:%.*]] = load i128, ptr [[A_ADDR]], align 16 -// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[E]], i32 0, i32 0 +// CHECK-NEXT: store i128 [[A:%.*]], ptr [[A_ADDR]], align 16 +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr [[A_ADDR]], align 16 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[E]], i32 0, i32 0 +// CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[E]], i32 0, i32 1 // CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8 -// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[E]], i32 0, i32 1 -// CHECK-NEXT: [[TMP6:%.*]] = load i64, ptr [[TMP5]], align 8 -// CHECK-NEXT: store i128 [[TMP2]], ptr [[COERCE]], align 16 -// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0 -// CHECK-NEXT: [[TMP8:%.*]] = load i64, ptr [[TMP7]], align 16 -// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1 -// CHECK-NEXT: [[TMP10:%.*]] = load i64, ptr [[TMP9]], align 8 -// CHECK-NEXT: [[CALL:%.*]] = call ptr @m4(i64 [[TMP4]], i64 [[TMP6]], i64 noundef [[TMP8]], i64 noundef [[TMP10]]) -// CHECK-NEXT: [[CASTED_ALIGN:%.*]] = trunc i128 [[TMP2]] to i64 +// CHECK-NEXT: [[CALL:%.*]] = call ptr @m4(i64 [[TMP2]], i64 [[TMP4]], i128 noundef [[TMP0]]) +// CHECK-NEXT: [[CASTED_ALIGN:%.*]] = trunc i128 [[TMP0]] to i64 // CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[CALL]], i64 [[CASTED_ALIGN]]) ] -// CHECK-NEXT: [[TMP11:%.*]] = load i32, ptr [[CALL]], align 4 -// CHECK-NEXT: ret i32 [[TMP11]] +// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[CALL]], align 4 +// CHECK-NEXT: ret i32 [[TMP5]] // __INT32_TYPE__ test6(__int128_t a) { struct MultiArgs e; diff --git a/clang/test/CodeGen/arm-aapcs-vfp.c b/clang/test/CodeGen/arm-aapcs-vfp.c index 6581929f99f14..e60ed1e52c33a 100644 --- a/clang/test/CodeGen/arm-aapcs-vfp.c +++ b/clang/test/CodeGen/arm-aapcs-vfp.c @@ -65,7 +65,7 @@ struct big_struct { float f4; }; // CHECK: define{{.*}} arm_aapcs_vfpcc void @test_big([5 x i32] %{{.*}}) -// CHECK64: define{{.*}} void @test_big(ptr noundef %{{.*}}) +// CHECK64: define{{.*}} void @test_big(ptr dead_on_return noundef %{{.*}}) // CHECK64: call void @llvm.memcpy // CHECK64: call void @big_callee(ptr extern void big_callee(struct big_struct); diff --git a/clang/test/CodeGen/arm-abi-vector.c b/clang/test/CodeGen/arm-abi-vector.c index c2a8902007980..93b770878c3fa 100644 --- a/clang/test/CodeGen/arm-abi-vector.c +++ b/clang/test/CodeGen/arm-abi-vector.c @@ -177,11 +177,11 @@ double varargs_vec_19c(int fixed, ...) { double test_19c(__char19 *in) { // CHECK: test_19c -// CHECK: call arm_aapcscc double (i32, ...) @varargs_vec_19c(i32 noundef 19, ptr noundef {{%.*}}) +// CHECK: call arm_aapcscc double (i32, ...) @varargs_vec_19c(i32 noundef 19, ptr dead_on_return noundef {{%.*}}) // APCS-GNU: test_19c -// APCS-GNU: call double (i32, ...) @varargs_vec_19c(i32 noundef 19, ptr noundef {{%.*}}) +// APCS-GNU: call double (i32, ...) @varargs_vec_19c(i32 noundef 19, ptr dead_on_return noundef {{%.*}}) // ANDROID: test_19c -// ANDROID: call double (i32, ...) @varargs_vec_19c(i32 noundef 19, ptr noundef {{%.*}}) +// ANDROID: call double (i32, ...) @varargs_vec_19c(i32 noundef 19, ptr dead_on_return noundef {{%.*}}) return varargs_vec_19c(19, *in); } diff --git a/clang/test/CodeGen/arm-swiftcall.c b/clang/test/CodeGen/arm-swiftcall.c index 677b878c6765d..55c22a45fd8de 100644 --- a/clang/test/CodeGen/arm-swiftcall.c +++ b/clang/test/CodeGen/arm-swiftcall.c @@ -261,7 +261,7 @@ TEST(struct_big_1) // CHECK-LABEL: define{{.*}} void @return_struct_big_1({{.*}} dead_on_unwind noalias writable sret({{.*}}) // Should not be byval. -// CHECK-LABEL: define{{.*}} void @take_struct_big_1(ptr{{( %.*)?}}) +// CHECK-LABEL: define{{.*}} void @take_struct_big_1(ptr dead_on_return{{( %.*)?}}) /*****************************************************************************/ /********************************* TYPE MERGING ******************************/ diff --git a/clang/test/CodeGen/arm64-abi-vector.c b/clang/test/CodeGen/arm64-abi-vector.c index 81e42315c883b..cf50cdd2fe86e 100644 --- a/clang/test/CodeGen/arm64-abi-vector.c +++ b/clang/test/CodeGen/arm64-abi-vector.c @@ -128,7 +128,7 @@ double varargs_vec_19c(int fixed, ...) { double test_19c(__char19 *in) { // CHECK: test_19c -// CHECK: call double (i32, ...) @varargs_vec_19c(i32 noundef 19, ptr noundef {{%.*}}) +// CHECK: call double (i32, ...) @varargs_vec_19c(i32 noundef 19, ptr dead_on_return noundef {{%.*}}) return varargs_vec_19c(19, *in); } @@ -211,7 +211,7 @@ double varargs_vec_5i(int fixed, ...) { double test_5i(__int5 *in) { // CHECK: test_5i -// CHECK: call double (i32, ...) @varargs_vec_5i(i32 noundef 5, ptr noundef {{%.*}}) +// CHECK: call double (i32, ...) @varargs_vec_5i(i32 noundef 5, ptr dead_on_return noundef {{%.*}}) return varargs_vec_5i(5, *in); } @@ -231,7 +231,7 @@ double varargs_vec_3d(int fixed, ...) { double test_3d(__double3 *in) { // CHECK: test_3d -// CHECK: call double (i32, ...) @varargs_vec_3d(i32 noundef 3, ptr noundef {{%.*}}) +// CHECK: call double (i32, ...) @varargs_vec_3d(i32 noundef 3, ptr dead_on_return noundef {{%.*}}) return varargs_vec_3d(3, *in); } @@ -291,7 +291,7 @@ double test(__char3 *c3, __char5 *c5, __char9 *c9, __char19 *c19, __short3 *s3, __short5 *s5, __int3 *i3, __int5 *i5, __double3 *d3) { double ret = varargs_vec(3, *c3, *c5, *c9, *c19, *s3, *s5, *i3, *i5, *d3); -// CHECK: call double (i32, ...) @varargs_vec(i32 noundef 3, i32 {{%.*}}, <2 x i32> {{%.*}}, <4 x i32> {{%.*}}, ptr noundef {{%.*}}, <2 x i32> {{%.*}}, <4 x i32> {{%.*}}, <4 x i32> {{%.*}}, ptr noundef {{%.*}}, ptr noundef {{%.*}}) +// CHECK: call double (i32, ...) @varargs_vec(i32 noundef 3, i32 {{%.*}}, <2 x i32> {{%.*}}, <4 x i32> {{%.*}}, ptr dead_on_return noundef {{%.*}}, <2 x i32> {{%.*}}, <4 x i32> {{%.*}}, <4 x i32> {{%.*}}, ptr dead_on_return noundef {{%.*}}, ptr dead_on_return noundef {{%.*}}) return ret; } @@ -350,7 +350,7 @@ __attribute__((noinline)) double args_vec_19c(int fixed, __char19 c19) { double fixed_19c(__char19 *in) { // CHECK: fixed_19c -// CHECK: call double @args_vec_19c(i32 noundef 19, ptr noundef {{%.*}}) +// CHECK: call double @args_vec_19c(i32 noundef 19, ptr dead_on_return noundef {{%.*}}) return args_vec_19c(19, *in); } @@ -409,7 +409,7 @@ __attribute__((noinline)) double args_vec_5i(int fixed, __int5 c5) { double fixed_5i(__int5 *in) { // CHECK: fixed_5i -// CHECK: call double @args_vec_5i(i32 noundef 5, ptr noundef {{%.*}}) +// CHECK: call double @args_vec_5i(i32 noundef 5, ptr dead_on_return noundef {{%.*}}) return args_vec_5i(5, *in); } @@ -424,6 +424,6 @@ __attribute__((noinline)) double args_vec_3d(int fixed, __double3 c3) { double fixed_3d(__double3 *in) { // CHECK: fixed_3d -// CHECK: call double @args_vec_3d(i32 noundef 3, ptr noundef {{%.*}}) +// CHECK: call double @args_vec_3d(i32 noundef 3, ptr dead_on_return noundef {{%.*}}) return args_vec_3d(3, *in); } diff --git a/clang/test/CodeGen/arm64-arguments.c b/clang/test/CodeGen/arm64-arguments.c index 4c4f85d923e78..2e3ab388432f6 100644 --- a/clang/test/CodeGen/arm64-arguments.c +++ b/clang/test/CodeGen/arm64-arguments.c @@ -163,7 +163,7 @@ void f32(struct s32 s) { } // A composite type larger than 16 bytes should be passed indirectly. struct s33 { char buf[32*32]; }; void f33(struct s33 s) { } -// CHECK: define{{.*}} void @f33(ptr noundef %s) +// CHECK: define{{.*}} void @f33(ptr dead_on_return noundef %s) struct s34 { char c; }; void f34(struct s34 s); @@ -226,9 +226,9 @@ T_float32x2 f1_0(T_float32x2 a0) { return a0; } // CHECK: define{{.*}} <4 x float> @f1_1(<4 x float> noundef %{{.*}}) T_float32x4 f1_1(T_float32x4 a0) { return a0; } // Vector with length bigger than 16-byte is illegal and is passed indirectly. -// CHECK: define{{.*}} void @f1_2(ptr dead_on_unwind noalias writable sret(<8 x float>) align 16 %{{.*}}, ptr noundef %0) +// CHECK: define{{.*}} void @f1_2(ptr dead_on_unwind noalias writable sret(<8 x float>) align 16 %{{.*}}, ptr dead_on_return noundef %0) T_float32x8 f1_2(T_float32x8 a0) { return a0; } -// CHECK: define{{.*}} void @f1_3(ptr dead_on_unwind noalias writable sret(<16 x float>) align 16 %{{.*}}, ptr noundef %0) +// CHECK: define{{.*}} void @f1_3(ptr dead_on_unwind noalias writable sret(<16 x float>) align 16 %{{.*}}, ptr dead_on_return noundef %0) T_float32x16 f1_3(T_float32x16 a0) { return a0; } // Testing alignment with aggregates: HFA, aggregates with size <= 16 bytes and @@ -278,7 +278,7 @@ struct s37 typedef struct s37 s37_with_align; int32x4_t f37(int i, s37_with_align s1, s37_with_align s2) { -// CHECK: define{{.*}} <4 x i32> @f37(i32 noundef %i, ptr noundef %s1, ptr noundef %s2) +// CHECK: define{{.*}} <4 x i32> @f37(i32 noundef %i, ptr dead_on_return noundef %s1, ptr dead_on_return noundef %s2) // CHECK: load <4 x i32>, ptr %s1, align 16 // CHECK: load <4 x i32>, ptr %s2, align 16 int32x4_t v = vaddq_s32(*(int32x4_t *)&s1, @@ -292,7 +292,7 @@ int32x4_t caller37() { // CHECK: %[[b:.*]] = alloca %struct.s37, align 16 // CHECK: call void @llvm.memcpy // CHECK: call void @llvm.memcpy -// CHECK: call <4 x i32> @f37(i32 noundef 3, ptr noundef %[[a]], ptr noundef %[[b]]) +// CHECK: call <4 x i32> @f37(i32 noundef 3, ptr dead_on_return noundef %[[a]], ptr dead_on_return noundef %[[b]]) return f37(3, g37, g37); } @@ -530,7 +530,7 @@ typedef struct s42 s42_no_align; // passing structs in registers __attribute__ ((noinline)) int f42(int i, s42_no_align s1, s42_no_align s2) { -// CHECK: define{{.*}} i32 @f42(i32 noundef %i, ptr noundef %s1, ptr noundef %s2) +// CHECK: define{{.*}} i32 @f42(i32 noundef %i, ptr dead_on_return noundef %s1, ptr dead_on_return noundef %s2) // CHECK: getelementptr inbounds nuw %struct.s42, ptr %s1, i32 0, i32 0 // CHECK: getelementptr inbounds nuw %struct.s42, ptr %s2, i32 0, i32 0 // CHECK: getelementptr inbounds nuw %struct.s42, ptr %s1, i32 0, i32 1 @@ -545,14 +545,14 @@ int caller42() { // CHECK: %[[b:.*]] = alloca %struct.s42, align 4 // CHECK: call void @llvm.memcpy.p0.p0.i64 // CHECK: call void @llvm.memcpy.p0.p0.i64 -// CHECK: call i32 @f42(i32 noundef 3, ptr noundef %[[a]], ptr noundef %[[b]]) +// CHECK: call i32 @f42(i32 noundef 3, ptr dead_on_return noundef %[[a]], ptr dead_on_return noundef %[[b]]) return f42(3, g42, g42_2); } // passing structs on stack __attribute__ ((noinline)) int f42_stack(int i, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, s42_no_align s1, s42_no_align s2) { -// CHECK: define{{.*}} i32 @f42_stack(i32 noundef %i, i32 noundef %i2, i32 noundef %i3, i32 noundef %i4, i32 noundef %i5, i32 noundef %i6, i32 noundef %i7, i32 noundef %i8, i32 noundef %i9, ptr noundef %s1, ptr noundef %s2) +// CHECK: define{{.*}} i32 @f42_stack(i32 noundef %i, i32 noundef %i2, i32 noundef %i3, i32 noundef %i4, i32 noundef %i5, i32 noundef %i6, i32 noundef %i7, i32 noundef %i8, i32 noundef %i9, ptr dead_on_return noundef %s1, ptr dead_on_return noundef %s2) // CHECK: getelementptr inbounds nuw %struct.s42, ptr %s1, i32 0, i32 0 // CHECK: getelementptr inbounds nuw %struct.s42, ptr %s2, i32 0, i32 0 // CHECK: getelementptr inbounds nuw %struct.s42, ptr %s1, i32 0, i32 1 @@ -565,7 +565,7 @@ int caller42_stack() { // CHECK: %[[b:.*]] = alloca %struct.s42, align 4 // CHECK: call void @llvm.memcpy.p0.p0.i64 // CHECK: call void @llvm.memcpy.p0.p0.i64 -// CHECK: call i32 @f42_stack(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 noundef 4, i32 noundef 5, i32 noundef 6, i32 noundef 7, i32 noundef 8, i32 noundef 9, ptr noundef %[[a]], ptr noundef %[[b]]) +// CHECK: call i32 @f42_stack(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 noundef 4, i32 noundef 5, i32 noundef 6, i32 noundef 7, i32 noundef 8, i32 noundef 9, ptr dead_on_return noundef %[[a]], ptr dead_on_return noundef %[[b]]) return f42_stack(1, 2, 3, 4, 5, 6, 7, 8, 9, g42, g42_2); } @@ -583,7 +583,7 @@ typedef struct s43 s43_with_align; // passing aligned structs in registers __attribute__ ((noinline)) int f43(int i, s43_with_align s1, s43_with_align s2) { -// CHECK: define{{.*}} i32 @f43(i32 noundef %i, ptr noundef %s1, ptr noundef %s2) +// CHECK: define{{.*}} i32 @f43(i32 noundef %i, ptr dead_on_return noundef %s1, ptr dead_on_return noundef %s2) // CHECK: getelementptr inbounds nuw %struct.s43, ptr %s1, i32 0, i32 0 // CHECK: getelementptr inbounds nuw %struct.s43, ptr %s2, i32 0, i32 0 // CHECK: getelementptr inbounds nuw %struct.s43, ptr %s1, i32 0, i32 1 @@ -598,14 +598,14 @@ int caller43() { // CHECK: %[[b:.*]] = alloca %struct.s43, align 16 // CHECK: call void @llvm.memcpy.p0.p0.i64 // CHECK: call void @llvm.memcpy.p0.p0.i64 -// CHECK: call i32 @f43(i32 noundef 3, ptr noundef %[[a]], ptr noundef %[[b]]) +// CHECK: call i32 @f43(i32 noundef 3, ptr dead_on_return noundef %[[a]], ptr dead_on_return noundef %[[b]]) return f43(3, g43, g43_2); } // passing aligned structs on stack __attribute__ ((noinline)) int f43_stack(int i, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, s43_with_align s1, s43_with_align s2) { -// CHECK: define{{.*}} i32 @f43_stack(i32 noundef %i, i32 noundef %i2, i32 noundef %i3, i32 noundef %i4, i32 noundef %i5, i32 noundef %i6, i32 noundef %i7, i32 noundef %i8, i32 noundef %i9, ptr noundef %s1, ptr noundef %s2) +// CHECK: define{{.*}} i32 @f43_stack(i32 noundef %i, i32 noundef %i2, i32 noundef %i3, i32 noundef %i4, i32 noundef %i5, i32 noundef %i6, i32 noundef %i7, i32 noundef %i8, i32 noundef %i9, ptr dead_on_return noundef %s1, ptr dead_on_return noundef %s2) // CHECK: getelementptr inbounds nuw %struct.s43, ptr %s1, i32 0, i32 0 // CHECK: getelementptr inbounds nuw %struct.s43, ptr %s2, i32 0, i32 0 // CHECK: getelementptr inbounds nuw %struct.s43, ptr %s1, i32 0, i32 1 @@ -618,7 +618,7 @@ int caller43_stack() { // CHECK: %[[b:.*]] = alloca %struct.s43, align 16 // CHECK: call void @llvm.memcpy.p0.p0.i64 // CHECK: call void @llvm.memcpy.p0.p0.i64 -// CHECK: call i32 @f43_stack(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 noundef 4, i32 noundef 5, i32 noundef 6, i32 noundef 7, i32 noundef 8, i32 noundef 9, ptr noundef %[[a]], ptr noundef %[[b]]) +// CHECK: call i32 @f43_stack(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 noundef 4, i32 noundef 5, i32 noundef 6, i32 noundef 7, i32 noundef 8, i32 noundef 9, ptr dead_on_return noundef %[[a]], ptr dead_on_return noundef %[[b]]) return f43_stack(1, 2, 3, 4, 5, 6, 7, 8, 9, g43, g43_2); } diff --git a/clang/test/CodeGen/arm64-microsoft-arguments.cpp b/clang/test/CodeGen/arm64-microsoft-arguments.cpp index 85472645acb3b..a0a81be54325f 100644 --- a/clang/test/CodeGen/arm64-microsoft-arguments.cpp +++ b/clang/test/CodeGen/arm64-microsoft-arguments.cpp @@ -29,7 +29,7 @@ S2 f2() { // Pass and return for type size > 16 bytes. // CHECK: define {{.*}} void @{{.*}}f3{{.*}}(ptr dead_on_unwind noalias writable sret(%struct.S3) align 4 %agg.result) -// CHECK: call void {{.*}}func3{{.*}}(ptr dead_on_unwind writable sret(%struct.S3) align 4 %agg.result, ptr noundef %agg.tmp) +// CHECK: call void {{.*}}func3{{.*}}(ptr dead_on_unwind writable sret(%struct.S3) align 4 %agg.result, ptr dead_on_return noundef %agg.tmp) struct S3 { int a[5]; }; diff --git a/clang/test/CodeGen/armv7k-abi.c b/clang/test/CodeGen/armv7k-abi.c index 872e6423a4a99..6a781bc04d042 100644 --- a/clang/test/CodeGen/armv7k-abi.c +++ b/clang/test/CodeGen/armv7k-abi.c @@ -39,7 +39,7 @@ typedef struct { double z; } BigStruct; -// CHECK: define{{.*}} void @big_struct_indirect(ptr noundef %b) +// CHECK: define{{.*}} void @big_struct_indirect(ptr dead_on_return noundef %b) void big_struct_indirect(BigStruct b) {} // CHECK: define{{.*}} void @return_big_struct_indirect(ptr dead_on_unwind noalias writable sret diff --git a/clang/test/CodeGen/atomic-arm64.c b/clang/test/CodeGen/atomic-arm64.c index d2a30a3b6e66f..d539cad0c6a7d 100644 --- a/clang/test/CodeGen/atomic-arm64.c +++ b/clang/test/CodeGen/atomic-arm64.c @@ -57,7 +57,7 @@ void test3(pointer_pair_t pair) { } // CHECK-LABEL:define{{.*}} void @test4( -// CHECK-SAME: ptr noundef [[QUAD:%.*]]) +// CHECK-SAME: ptr dead_on_return noundef [[QUAD:%.*]]) // CHECK: [[QUAD_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[TEMP:%.*]] = alloca [[QUAD_T:%.*]], align 8 // CHECK-NEXT: store ptr [[QUAD]], ptr [[QUAD_INDIRECT_ADDR]] diff --git a/clang/test/CodeGen/attr-noundef.cpp b/clang/test/CodeGen/attr-noundef.cpp index abdf9496bd396..619dbec7678db 100644 --- a/clang/test/CodeGen/attr-noundef.cpp +++ b/clang/test/CodeGen/attr-noundef.cpp @@ -27,7 +27,7 @@ struct NoCopy { NoCopy ret_nocopy() { return {}; } void pass_nocopy(NoCopy e) {} // CHECK: [[DEF]] void @{{.*}}ret_nocopy{{.*}}(ptr dead_on_unwind noalias writable sret({{[^)]+}}) align 4 % -// CHECK: [[DEF]] void @{{.*}}pass_nocopy{{.*}}(ptr noundef % +// CHECK: [[DEF]] void @{{.*}}pass_nocopy{{.*}}(ptr dead_on_return noundef % struct Huge { int a[1024]; @@ -35,7 +35,8 @@ struct Huge { Huge ret_huge() { return {}; } void pass_huge(Huge h) {} // CHECK: [[DEF]] void @{{.*}}ret_huge{{.*}}(ptr dead_on_unwind noalias writable sret({{[^)]+}}) align 4 % -// CHECK: [[DEF]] void @{{.*}}pass_huge{{.*}}(ptr noundef +// CHECK-INTEL: [[DEF]] void @{{.*}}pass_huge{{.*}}(ptr noundef +// CHECK-AARCH: [[DEF]] void @{{.*}}pass_huge{{.*}}(ptr dead_on_return noundef } // namespace check_structs //************ Passing unions by value @@ -59,7 +60,7 @@ union NoCopy { NoCopy ret_nocopy() { return {}; } void pass_nocopy(NoCopy e) {} // CHECK: [[DEF]] void @{{.*}}ret_nocopy{{.*}}(ptr dead_on_unwind noalias writable sret({{[^)]+}}) align 4 % -// CHECK: [[DEF]] void @{{.*}}pass_nocopy{{.*}}(ptr noundef % +// CHECK: [[DEF]] void @{{.*}}pass_nocopy{{.*}}(ptr dead_on_return noundef % } // namespace check_unions //************ Passing `this` pointers diff --git a/clang/test/CodeGen/builtin-maximumnum-minimumnum.c b/clang/test/CodeGen/builtin-maximumnum-minimumnum.c new file mode 100644 index 0000000000000..ea9d2e7a4ed38 --- /dev/null +++ b/clang/test/CodeGen/builtin-maximumnum-minimumnum.c @@ -0,0 +1,171 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -x c++ -std=c++20 -disable-llvm-passes -O3 -triple x86_64 %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK + +typedef _Float16 half8 __attribute__((ext_vector_type(8))); +typedef __bf16 bf16x8 __attribute__((ext_vector_type(8))); +typedef float float4 __attribute__((ext_vector_type(4))); +typedef double double2 __attribute__((ext_vector_type(2))); +typedef long double ldouble2 __attribute__((ext_vector_type(2))); + +// CHECK-LABEL: define dso_local noundef <8 x half> @_Z7pfmin16Dv8_DF16_S_( +// CHECK-SAME: <8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <8 x half>, align 16 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <8 x half>, align 16 +// CHECK-NEXT: store <8 x half> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2:![0-9]+]] +// CHECK-NEXT: store <8 x half> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x half>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x half>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[ELT_MINIMUMNUM:%.*]] = call <8 x half> @llvm.minimumnum.v8f16(<8 x half> [[TMP0]], <8 x half> [[TMP1]]) +// CHECK-NEXT: ret <8 x half> [[ELT_MINIMUMNUM]] +// +half8 pfmin16(half8 a, half8 b) { + return __builtin_elementwise_minimumnum(a, b); +} +// CHECK-LABEL: define dso_local noundef <8 x bfloat> @_Z8pfmin16bDv8_DF16bS_( +// CHECK-SAME: <8 x bfloat> noundef [[A:%.*]], <8 x bfloat> noundef [[B:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <8 x bfloat>, align 16 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <8 x bfloat>, align 16 +// CHECK-NEXT: store <8 x bfloat> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: store <8 x bfloat> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x bfloat>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x bfloat>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[ELT_MINIMUMNUM:%.*]] = call <8 x bfloat> @llvm.minimumnum.v8bf16(<8 x bfloat> [[TMP0]], <8 x bfloat> [[TMP1]]) +// CHECK-NEXT: ret <8 x bfloat> [[ELT_MINIMUMNUM]] +// +bf16x8 pfmin16b(bf16x8 a, bf16x8 b) { + return __builtin_elementwise_minimumnum(a, b); +} +// CHECK-LABEL: define dso_local noundef <4 x float> @_Z7pfmin32Dv4_fS_( +// CHECK-SAME: <4 x float> noundef [[A:%.*]], <4 x float> noundef [[B:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: store <4 x float> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: store <4 x float> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[ELT_MINIMUMNUM:%.*]] = call <4 x float> @llvm.minimumnum.v4f32(<4 x float> [[TMP0]], <4 x float> [[TMP1]]) +// CHECK-NEXT: ret <4 x float> [[ELT_MINIMUMNUM]] +// +float4 pfmin32(float4 a, float4 b) { + return __builtin_elementwise_minimumnum(a, b); +} +// CHECK-LABEL: define dso_local noundef <2 x double> @_Z7pfmin64Dv2_dS_( +// CHECK-SAME: <2 x double> noundef [[A:%.*]], <2 x double> noundef [[B:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: store <2 x double> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: store <2 x double> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[ELT_MINIMUMNUM:%.*]] = call <2 x double> @llvm.minimumnum.v2f64(<2 x double> [[TMP0]], <2 x double> [[TMP1]]) +// CHECK-NEXT: ret <2 x double> [[ELT_MINIMUMNUM]] +// +double2 pfmin64(double2 a, double2 b) { + return __builtin_elementwise_minimumnum(a, b); +} +// CHECK-LABEL: define dso_local noundef <2 x x86_fp80> @_Z7pfmin80Dv2_eS_( +// CHECK-SAME: ptr noundef byval(<2 x x86_fp80>) align 32 [[TMP0:%.*]], ptr noundef byval(<2 x x86_fp80>) align 32 [[TMP1:%.*]]) #[[ATTR2:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <2 x x86_fp80>, align 32 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <2 x x86_fp80>, align 32 +// CHECK-NEXT: [[A:%.*]] = load <2 x x86_fp80>, ptr [[TMP0]], align 32, !tbaa [[TBAA2]] +// CHECK-NEXT: [[B:%.*]] = load <2 x x86_fp80>, ptr [[TMP1]], align 32, !tbaa [[TBAA2]] +// CHECK-NEXT: store <2 x x86_fp80> [[A]], ptr [[A_ADDR]], align 32, !tbaa [[TBAA2]] +// CHECK-NEXT: store <2 x x86_fp80> [[B]], ptr [[B_ADDR]], align 32, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP2:%.*]] = load <2 x x86_fp80>, ptr [[A_ADDR]], align 32, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP3:%.*]] = load <2 x x86_fp80>, ptr [[B_ADDR]], align 32, !tbaa [[TBAA2]] +// CHECK-NEXT: [[ELT_MINIMUMNUM:%.*]] = call <2 x x86_fp80> @llvm.minimumnum.v2f80(<2 x x86_fp80> [[TMP2]], <2 x x86_fp80> [[TMP3]]) +// CHECK-NEXT: ret <2 x x86_fp80> [[ELT_MINIMUMNUM]] +// +ldouble2 pfmin80(ldouble2 a, ldouble2 b) { + return __builtin_elementwise_minimumnum(a, b); +} + +// CHECK-LABEL: define dso_local noundef <8 x half> @_Z7pfmax16Dv8_DF16_S_( +// CHECK-SAME: <8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <8 x half>, align 16 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <8 x half>, align 16 +// CHECK-NEXT: store <8 x half> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: store <8 x half> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x half>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x half>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[ELT_MAXIMUMNUM:%.*]] = call <8 x half> @llvm.maximumnum.v8f16(<8 x half> [[TMP0]], <8 x half> [[TMP1]]) +// CHECK-NEXT: ret <8 x half> [[ELT_MAXIMUMNUM]] +// +half8 pfmax16(half8 a, half8 b) { + return __builtin_elementwise_maximumnum(a, b); +} +// CHECK-LABEL: define dso_local noundef <8 x bfloat> @_Z8pfmax16bDv8_DF16bS_( +// CHECK-SAME: <8 x bfloat> noundef [[A:%.*]], <8 x bfloat> noundef [[B:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <8 x bfloat>, align 16 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <8 x bfloat>, align 16 +// CHECK-NEXT: store <8 x bfloat> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: store <8 x bfloat> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x bfloat>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x bfloat>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[ELT_MAXIMUMNUM:%.*]] = call <8 x bfloat> @llvm.maximumnum.v8bf16(<8 x bfloat> [[TMP0]], <8 x bfloat> [[TMP1]]) +// CHECK-NEXT: ret <8 x bfloat> [[ELT_MAXIMUMNUM]] +// +bf16x8 pfmax16b(bf16x8 a, bf16x8 b) { + return __builtin_elementwise_maximumnum(a, b); +} +// CHECK-LABEL: define dso_local noundef <4 x float> @_Z7pfmax32Dv4_fS_( +// CHECK-SAME: <4 x float> noundef [[A:%.*]], <4 x float> noundef [[B:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: store <4 x float> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: store <4 x float> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[ELT_MAXIMUMNUM:%.*]] = call <4 x float> @llvm.maximumnum.v4f32(<4 x float> [[TMP0]], <4 x float> [[TMP1]]) +// CHECK-NEXT: ret <4 x float> [[ELT_MAXIMUMNUM]] +// +float4 pfmax32(float4 a, float4 b) { + return __builtin_elementwise_maximumnum(a, b); +} +// CHECK-LABEL: define dso_local noundef <2 x double> @_Z7pfmax64Dv2_dS_( +// CHECK-SAME: <2 x double> noundef [[A:%.*]], <2 x double> noundef [[B:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: store <2 x double> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: store <2 x double> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[ELT_MAXIMUMNUM:%.*]] = call <2 x double> @llvm.maximumnum.v2f64(<2 x double> [[TMP0]], <2 x double> [[TMP1]]) +// CHECK-NEXT: ret <2 x double> [[ELT_MAXIMUMNUM]] +// +double2 pfmax64(double2 a, double2 b) { + return __builtin_elementwise_maximumnum(a, b); +} + +// CHECK-LABEL: define dso_local noundef <2 x x86_fp80> @_Z7pfmax80Dv2_eS_( +// CHECK-SAME: ptr noundef byval(<2 x x86_fp80>) align 32 [[TMP0:%.*]], ptr noundef byval(<2 x x86_fp80>) align 32 [[TMP1:%.*]]) #[[ATTR2]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <2 x x86_fp80>, align 32 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <2 x x86_fp80>, align 32 +// CHECK-NEXT: [[A:%.*]] = load <2 x x86_fp80>, ptr [[TMP0]], align 32, !tbaa [[TBAA2]] +// CHECK-NEXT: [[B:%.*]] = load <2 x x86_fp80>, ptr [[TMP1]], align 32, !tbaa [[TBAA2]] +// CHECK-NEXT: store <2 x x86_fp80> [[A]], ptr [[A_ADDR]], align 32, !tbaa [[TBAA2]] +// CHECK-NEXT: store <2 x x86_fp80> [[B]], ptr [[B_ADDR]], align 32, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP2:%.*]] = load <2 x x86_fp80>, ptr [[A_ADDR]], align 32, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP3:%.*]] = load <2 x x86_fp80>, ptr [[B_ADDR]], align 32, !tbaa [[TBAA2]] +// CHECK-NEXT: [[ELT_MINIMUMNUM:%.*]] = call <2 x x86_fp80> @llvm.minimumnum.v2f80(<2 x x86_fp80> [[TMP2]], <2 x x86_fp80> [[TMP3]]) +// CHECK-NEXT: ret <2 x x86_fp80> [[ELT_MINIMUMNUM]] +// +ldouble2 pfmax80(ldouble2 a, ldouble2 b) { + return __builtin_elementwise_minimumnum(a, b); +} + +//. +// CHECK: [[TBAA2]] = !{[[META3:![0-9]+]], [[META3]], i64 0} +// CHECK: [[META3]] = !{!"omnipotent char", [[META4:![0-9]+]], i64 0} +// CHECK: [[META4]] = !{!"Simple C++ TBAA"} +//. diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c index eda6c67fdad00..aa9965b815983 100644 --- a/clang/test/CodeGen/builtins.c +++ b/clang/test/CodeGen/builtins.c @@ -956,36 +956,24 @@ void test_builtin_os_log_errno(void) { void test_builtin_os_log_long_double(void *buf, long double ld) { // CHECK: %[[BUF_ADDR:.*]] = alloca ptr, align 8 // CHECK: %[[LD_ADDR:.*]] = alloca x86_fp80, align 16 - // CHECK: %[[COERCE:.*]] = alloca i128, align 16 // CHECK: store ptr %[[BUF]], ptr %[[BUF_ADDR]], align 8 // CHECK: store x86_fp80 %[[LD]], ptr %[[LD_ADDR]], align 16 // CHECK: %[[V0:.*]] = load ptr, ptr %[[BUF_ADDR]], align 8 // CHECK: %[[V1:.*]] = load x86_fp80, ptr %[[LD_ADDR]], align 16 // CHECK: %[[V2:.*]] = bitcast x86_fp80 %[[V1]] to i80 // CHECK: %[[V3:.*]] = zext i80 %[[V2]] to i128 - // CHECK: store i128 %[[V3]], ptr %[[COERCE]], align 16 - // CHECK: %[[V5:.*]] = getelementptr inbounds nuw { i64, i64 }, ptr %[[COERCE]], i32 0, i32 0 - // CHECK: %[[V6:.*]] = load i64, ptr %[[V5]], align 16 - // CHECK: %[[V7:.*]] = getelementptr inbounds nuw { i64, i64 }, ptr %[[COERCE]], i32 0, i32 1 - // CHECK: %[[V8:.*]] = load i64, ptr %[[V7]], align 8 - // CHECK: call void @__os_log_helper_1_0_1_16_0(ptr noundef %[[V0]], i64 noundef %[[V6]], i64 noundef %[[V8]]) + // CHECK: call void @__os_log_helper_1_0_1_16_0(ptr noundef %[[V0]], i128 noundef %[[V3]]) __builtin_os_log_format(buf, "%Lf", ld); } // CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_1_0_1_16_0 -// CHECK: (ptr noundef %[[BUFFER:.*]], i64 noundef %[[ARG0_COERCE0:.*]], i64 noundef %[[ARG0_COERCE1:.*]]) +// CHECK: (ptr noundef %[[BUFFER:.*]], i128 noundef %[[ARG0:.*]]) -// CHECK: %[[ARG0:.*]] = alloca i128, align 16 // CHECK: %[[BUFFER_ADDR:.*]] = alloca ptr, align 8 // CHECK: %[[ARG0_ADDR:.*]] = alloca i128, align 16 -// CHECK: %[[V1:.*]] = getelementptr inbounds nuw { i64, i64 }, ptr %[[ARG0]], i32 0, i32 0 -// CHECK: store i64 %[[ARG0_COERCE0]], ptr %[[V1]], align 16 -// CHECK: %[[V2:.*]] = getelementptr inbounds nuw { i64, i64 }, ptr %[[ARG0]], i32 0, i32 1 -// CHECK: store i64 %[[ARG0_COERCE1]], ptr %[[V2]], align 8 -// CHECK: %[[ARG01:.*]] = load i128, ptr %[[ARG0]], align 16 // CHECK: store ptr %[[BUFFER]], ptr %[[BUFFER_ADDR]], align 8 -// CHECK: store i128 %[[ARG01]], ptr %[[ARG0_ADDR]], align 16 +// CHECK: store i128 %[[ARG0]], ptr %[[ARG0_ADDR]], align 16 // CHECK: %[[BUF:.*]] = load ptr, ptr %[[BUFFER_ADDR]], align 8 // CHECK: %[[SUMMARY:.*]] = getelementptr i8, ptr %[[BUF]], i64 0 // CHECK: store i8 0, ptr %[[SUMMARY]], align 1 diff --git a/clang/test/CodeGen/cx-complex-range.c b/clang/test/CodeGen/cx-complex-range.c index cf74ab2dcca3f..fba692cac4492 100644 --- a/clang/test/CodeGen/cx-complex-range.c +++ b/clang/test/CodeGen/cx-complex-range.c @@ -1520,7 +1520,7 @@ void mulassignf(_Complex float *a, _Complex float b) { // PRMTD-NEXT: ret { double, double } [[DOTFCA_1_INSERT]] // // X86WINPRMTD-LABEL: define dso_local void @divd( -// X86WINPRMTD-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] { +// X86WINPRMTD-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr dead_on_return noundef [[A:%.*]], ptr dead_on_return noundef [[B:%.*]]) #[[ATTR0]] { // X86WINPRMTD-NEXT: entry: // X86WINPRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 0 // X86WINPRMTD-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 @@ -1744,7 +1744,7 @@ void mulassignf(_Complex float *a, _Complex float b) { // PRMTD_FAST-NEXT: ret { double, double } [[DOTFCA_1_INSERT]] // // X86WINPRMTD_STRICT-LABEL: define dso_local void @divd( -// X86WINPRMTD_STRICT-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] { +// X86WINPRMTD_STRICT-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr dead_on_return noundef [[A:%.*]], ptr dead_on_return noundef [[B:%.*]]) #[[ATTR0]] { // X86WINPRMTD_STRICT-NEXT: entry: // X86WINPRMTD_STRICT-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 0 // X86WINPRMTD_STRICT-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 @@ -1938,7 +1938,7 @@ _Complex double divd(_Complex double a, _Complex double b) { // PRMTD-NEXT: ret void // // X86WINPRMTD-LABEL: define dso_local void @divassignd( -// X86WINPRMTD-SAME: ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] { +// X86WINPRMTD-SAME: ptr noundef [[A:%.*]], ptr dead_on_return noundef [[B:%.*]]) #[[ATTR0]] { // X86WINPRMTD-NEXT: entry: // X86WINPRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 0 // X86WINPRMTD-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 @@ -2180,7 +2180,7 @@ _Complex double divd(_Complex double a, _Complex double b) { // PRMTD_FAST-NEXT: ret void // // X86WINPRMTD_STRICT-LABEL: define dso_local void @divassignd( -// X86WINPRMTD_STRICT-SAME: ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] { +// X86WINPRMTD_STRICT-SAME: ptr noundef [[A:%.*]], ptr dead_on_return noundef [[B:%.*]]) #[[ATTR0]] { // X86WINPRMTD_STRICT-NEXT: entry: // X86WINPRMTD_STRICT-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 0 // X86WINPRMTD_STRICT-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 @@ -2325,7 +2325,7 @@ void divassignd(_Complex double *a, _Complex double b) { // PRMTD-NEXT: ret { double, double } [[DOTFCA_1_INSERT]] // // X86WINPRMTD-LABEL: define dso_local void @muld( -// X86WINPRMTD-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] { +// X86WINPRMTD-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr dead_on_return noundef [[A:%.*]], ptr dead_on_return noundef [[B:%.*]]) #[[ATTR0]] { // X86WINPRMTD-NEXT: entry: // X86WINPRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 0 // X86WINPRMTD-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 @@ -2457,7 +2457,7 @@ void divassignd(_Complex double *a, _Complex double b) { // PRMTD_FAST-NEXT: ret { double, double } [[DOTFCA_1_INSERT]] // // X86WINPRMTD_STRICT-LABEL: define dso_local void @muld( -// X86WINPRMTD_STRICT-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] { +// X86WINPRMTD_STRICT-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr dead_on_return noundef [[A:%.*]], ptr dead_on_return noundef [[B:%.*]]) #[[ATTR0]] { // X86WINPRMTD_STRICT-NEXT: entry: // X86WINPRMTD_STRICT-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 0 // X86WINPRMTD_STRICT-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 @@ -2594,7 +2594,7 @@ _Complex double muld(_Complex double a, _Complex double b) { // PRMTD-NEXT: ret void // // X86WINPRMTD-LABEL: define dso_local void @mulassignd( -// X86WINPRMTD-SAME: ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] { +// X86WINPRMTD-SAME: ptr noundef [[A:%.*]], ptr dead_on_return noundef [[B:%.*]]) #[[ATTR0]] { // X86WINPRMTD-NEXT: entry: // X86WINPRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 0 // X86WINPRMTD-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 @@ -2744,7 +2744,7 @@ _Complex double muld(_Complex double a, _Complex double b) { // PRMTD_FAST-NEXT: ret void // // X86WINPRMTD_STRICT-LABEL: define dso_local void @mulassignd( -// X86WINPRMTD_STRICT-SAME: ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] { +// X86WINPRMTD_STRICT-SAME: ptr noundef [[A:%.*]], ptr dead_on_return noundef [[B:%.*]]) #[[ATTR0]] { // X86WINPRMTD_STRICT-NEXT: entry: // X86WINPRMTD_STRICT-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 0 // X86WINPRMTD_STRICT-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 @@ -2922,7 +2922,7 @@ void mulassignd(_Complex double *a, _Complex double b) { // PRMTD-NEXT: ret { x86_fp80, x86_fp80 } [[DOTFCA_1_INSERT]] // // X86WINPRMTD-LABEL: define dso_local void @divld( -// X86WINPRMTD-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] { +// X86WINPRMTD-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr dead_on_return noundef [[A:%.*]], ptr dead_on_return noundef [[B:%.*]]) #[[ATTR0]] { // X86WINPRMTD-NEXT: entry: // X86WINPRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 0 // X86WINPRMTD-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 @@ -3190,7 +3190,7 @@ void mulassignd(_Complex double *a, _Complex double b) { // PRMTD_FAST-NEXT: ret { x86_fp80, x86_fp80 } [[DOTFCA_1_INSERT]] // // X86WINPRMTD_STRICT-LABEL: define dso_local void @divld( -// X86WINPRMTD_STRICT-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] { +// X86WINPRMTD_STRICT-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr dead_on_return noundef [[A:%.*]], ptr dead_on_return noundef [[B:%.*]]) #[[ATTR0]] { // X86WINPRMTD_STRICT-NEXT: entry: // X86WINPRMTD_STRICT-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 0 // X86WINPRMTD_STRICT-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 @@ -3432,7 +3432,7 @@ _Complex long double divld(_Complex long double a, _Complex long double b) { // PRMTD-NEXT: ret void // // X86WINPRMTD-LABEL: define dso_local void @divassignld( -// X86WINPRMTD-SAME: ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] { +// X86WINPRMTD-SAME: ptr noundef [[A:%.*]], ptr dead_on_return noundef [[B:%.*]]) #[[ATTR0]] { // X86WINPRMTD-NEXT: entry: // X86WINPRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 0 // X86WINPRMTD-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 @@ -3702,7 +3702,7 @@ _Complex long double divld(_Complex long double a, _Complex long double b) { // PRMTD_FAST-NEXT: ret void // // X86WINPRMTD_STRICT-LABEL: define dso_local void @divassignld( -// X86WINPRMTD_STRICT-SAME: ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] { +// X86WINPRMTD_STRICT-SAME: ptr noundef [[A:%.*]], ptr dead_on_return noundef [[B:%.*]]) #[[ATTR0]] { // X86WINPRMTD_STRICT-NEXT: entry: // X86WINPRMTD_STRICT-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 0 // X86WINPRMTD_STRICT-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 @@ -3895,7 +3895,7 @@ void divassignld(_Complex long double *a, _Complex long double b) { // PRMTD-NEXT: ret { x86_fp80, x86_fp80 } [[DOTFCA_1_INSERT]] // // X86WINPRMTD-LABEL: define dso_local void @mulld( -// X86WINPRMTD-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] { +// X86WINPRMTD-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr dead_on_return noundef [[A:%.*]], ptr dead_on_return noundef [[B:%.*]]) #[[ATTR0]] { // X86WINPRMTD-NEXT: entry: // X86WINPRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 0 // X86WINPRMTD-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 @@ -4059,7 +4059,7 @@ void divassignld(_Complex long double *a, _Complex long double b) { // PRMTD_FAST-NEXT: ret { x86_fp80, x86_fp80 } [[DOTFCA_1_INSERT]] // // X86WINPRMTD_STRICT-LABEL: define dso_local void @mulld( -// X86WINPRMTD_STRICT-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] { +// X86WINPRMTD_STRICT-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr dead_on_return noundef [[A:%.*]], ptr dead_on_return noundef [[B:%.*]]) #[[ATTR0]] { // X86WINPRMTD_STRICT-NEXT: entry: // X86WINPRMTD_STRICT-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 0 // X86WINPRMTD_STRICT-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 @@ -4220,7 +4220,7 @@ _Complex long double mulld(_Complex long double a, _Complex long double b) { // PRMTD-NEXT: ret void // // X86WINPRMTD-LABEL: define dso_local void @mulassignld( -// X86WINPRMTD-SAME: ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] { +// X86WINPRMTD-SAME: ptr noundef [[A:%.*]], ptr dead_on_return noundef [[B:%.*]]) #[[ATTR0]] { // X86WINPRMTD-NEXT: entry: // X86WINPRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 0 // X86WINPRMTD-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 @@ -4386,7 +4386,7 @@ _Complex long double mulld(_Complex long double a, _Complex long double b) { // PRMTD_FAST-NEXT: ret void // // X86WINPRMTD_STRICT-LABEL: define dso_local void @mulassignld( -// X86WINPRMTD_STRICT-SAME: ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] { +// X86WINPRMTD_STRICT-SAME: ptr noundef [[A:%.*]], ptr dead_on_return noundef [[B:%.*]]) #[[ATTR0]] { // X86WINPRMTD_STRICT-NEXT: entry: // X86WINPRMTD_STRICT-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 0 // X86WINPRMTD_STRICT-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 @@ -4644,7 +4644,7 @@ void mulassignld(_Complex long double *a, _Complex long double b) { // PRMTD-NEXT: ret <2 x float> [[RETVAL_SROA_0_4_VEC_INSERT]] // // X86WINPRMTD-LABEL: define dso_local i64 @f1( -// X86WINPRMTD-SAME: i64 noundef [[A_COERCE:%.*]], ptr noundef [[B:%.*]], i64 noundef [[C_COERCE:%.*]]) #[[ATTR0]] { +// X86WINPRMTD-SAME: i64 noundef [[A_COERCE:%.*]], ptr dead_on_return noundef [[B:%.*]], i64 noundef [[C_COERCE:%.*]]) #[[ATTR0]] { // X86WINPRMTD-NEXT: entry: // X86WINPRMTD-NEXT: [[A_SROA_0_0_EXTRACT_TRUNC:%.*]] = trunc i64 [[A_COERCE]] to i32 // X86WINPRMTD-NEXT: [[TMP0:%.*]] = bitcast i32 [[A_SROA_0_0_EXTRACT_TRUNC]] to float @@ -5052,7 +5052,7 @@ void mulassignld(_Complex long double *a, _Complex long double b) { // PRMTD_FAST-NEXT: ret <2 x float> [[RETVAL_SROA_0_4_VEC_INSERT]] // // X86WINPRMTD_STRICT-LABEL: define dso_local i64 @f1( -// X86WINPRMTD_STRICT-SAME: i64 noundef [[A_COERCE:%.*]], ptr noundef [[B:%.*]], i64 noundef [[C_COERCE:%.*]]) #[[ATTR0]] { +// X86WINPRMTD_STRICT-SAME: i64 noundef [[A_COERCE:%.*]], ptr dead_on_return noundef [[B:%.*]], i64 noundef [[C_COERCE:%.*]]) #[[ATTR0]] { // X86WINPRMTD_STRICT-NEXT: entry: // X86WINPRMTD_STRICT-NEXT: [[A_SROA_0_0_EXTRACT_TRUNC:%.*]] = trunc i64 [[A_COERCE]] to i32 // X86WINPRMTD_STRICT-NEXT: [[TMP0:%.*]] = bitcast i32 [[A_SROA_0_0_EXTRACT_TRUNC]] to float diff --git a/clang/test/CodeGen/ext-int-cc.c b/clang/test/CodeGen/ext-int-cc.c index f31a4eb240c25..7cfd992fd48b4 100644 --- a/clang/test/CodeGen/ext-int-cc.c +++ b/clang/test/CodeGen/ext-int-cc.c @@ -32,10 +32,10 @@ // Make sure 128 and 64 bit versions are passed like integers. void ParamPassing(_BitInt(128) b, _BitInt(64) c) {} -// LIN64: define{{.*}} void @ParamPassing(i64 %{{.+}}, i64 %{{.+}}, i64 %{{.+}}) -// WIN64: define dso_local void @ParamPassing(ptr %{{.+}}, i64 %{{.+}}) -// LIN32: define{{.*}} void @ParamPassing(ptr %{{.+}}, i64 %{{.+}}) -// WIN32: define dso_local void @ParamPassing(ptr %{{.+}}, i64 %{{.+}}) +// LIN64: define{{.*}} void @ParamPassing(i128 %{{.+}}, i64 %{{.+}}) +// WIN64: define dso_local void @ParamPassing(ptr dead_on_return %{{.+}}, i64 %{{.+}}) +// LIN32: define{{.*}} void @ParamPassing(ptr dead_on_return %{{.+}}, i64 %{{.+}}) +// WIN32: define dso_local void @ParamPassing(ptr dead_on_return %{{.+}}, i64 %{{.+}}) // NVPTX64: define{{.*}} void @ParamPassing(i128 %{{.+}}, i64 %{{.+}}) // NVPTX: define{{.*}} void @ParamPassing(ptr byval(i128) align 8 %{{.+}}, i64 %{{.+}}) // SPARCV9: define{{.*}} void @ParamPassing(i128 %{{.+}}, i64 %{{.+}}) @@ -50,22 +50,22 @@ void ParamPassing(_BitInt(128) b, _BitInt(64) c) {} // ARC: define{{.*}} void @ParamPassing(ptr byval(i128) align 4 %{{.+}}, i64 inreg %{{.+}}) // XCORE: define{{.*}} void @ParamPassing(ptr byval(i128) align 4 %{{.+}}, i64 %{{.+}}) // RISCV64: define{{.*}} void @ParamPassing(i128 %{{.+}}, i64 %{{.+}}) -// RISCV32: define{{.*}} void @ParamPassing(ptr %{{.+}}, i64 %{{.+}}) +// RISCV32: define{{.*}} void @ParamPassing(ptr dead_on_return %{{.+}}, i64 %{{.+}}) // WASM: define{{.*}} void @ParamPassing(i128 %{{.+}}, i64 %{{.+}}) -// SYSTEMZ: define{{.*}} void @ParamPassing(ptr %{{.+}}, i64 %{{.+}}) +// SYSTEMZ: define{{.*}} void @ParamPassing(ptr dead_on_return %{{.+}}, i64 %{{.+}}) // PPC64: define{{.*}} void @ParamPassing(i128 %{{.+}}, i64 %{{.+}}) // PPC32: define{{.*}} void @ParamPassing(ptr byval(i128) align 8 %{{.+}}, i64 %{{.+}}) // AARCH64: define{{.*}} void @ParamPassing(i128 %{{.+}}, i64 %{{.+}}) // AARCH64DARWIN: define{{.*}} void @ParamPassing(i128 %{{.+}}, i64 %{{.+}}) // ARM: define{{.*}} arm_aapcscc void @ParamPassing(ptr byval(i128) align 8 %{{.+}}, i64 %{{.+}}) // LA64: define{{.*}} void @ParamPassing(i128 %{{.+}}, i64 %{{.+}}) -// LA32: define{{.*}} void @ParamPassing(ptr %{{.+}}, i64 %{{.+}}) +// LA32: define{{.*}} void @ParamPassing(ptr dead_on_return %{{.+}}, i64 %{{.+}}) void ParamPassing2(_BitInt(127) b, _BitInt(63) c) {} // LIN64: define{{.*}} void @ParamPassing2(i64 %{{.+}}, i64 %{{.+}}, i64 %{{.+}}) -// WIN64: define dso_local void @ParamPassing2(ptr %{{.+}}, i63 %{{.+}}) -// LIN32: define{{.*}} void @ParamPassing2(ptr %{{.+}}, i63 %{{.+}}) -// WIN32: define dso_local void @ParamPassing2(ptr %{{.+}}, i63 %{{.+}}) +// WIN64: define dso_local void @ParamPassing2(ptr dead_on_return %{{.+}}, i63 %{{.+}}) +// LIN32: define{{.*}} void @ParamPassing2(ptr dead_on_return %{{.+}}, i63 %{{.+}}) +// WIN32: define dso_local void @ParamPassing2(ptr dead_on_return %{{.+}}, i63 %{{.+}}) // NVPTX64: define{{.*}} void @ParamPassing2(i127 %{{.+}}, i63 %{{.+}}) // NVPTX: define{{.*}} void @ParamPassing2(ptr byval(i128) align 8 %{{.+}}, i63 %{{.+}}) // SPARCV9: define{{.*}} void @ParamPassing2(i127 %{{.+}}, i63 signext %{{.+}}) @@ -80,16 +80,16 @@ void ParamPassing2(_BitInt(127) b, _BitInt(63) c) {} // ARC: define{{.*}} void @ParamPassing2(ptr byval(i128) align 4 %{{.+}}, i63 inreg %{{.+}}) // XCORE: define{{.*}} void @ParamPassing2(ptr byval(i128) align 4 %{{.+}}, i63 %{{.+}}) // RISCV64: define{{.*}} void @ParamPassing2(i127 %{{.+}}, i63 signext %{{.+}}) -// RISCV32: define{{.*}} void @ParamPassing2(ptr %{{.+}}, i63 %{{.+}}) +// RISCV32: define{{.*}} void @ParamPassing2(ptr dead_on_return %{{.+}}, i63 %{{.+}}) // WASM: define{{.*}} void @ParamPassing2(i127 %{{.+}}, i63 %{{.+}}) -// SYSTEMZ: define{{.*}} void @ParamPassing2(ptr %{{.+}}, i63 signext %{{.+}}) +// SYSTEMZ: define{{.*}} void @ParamPassing2(ptr dead_on_return %{{.+}}, i63 signext %{{.+}}) // PPC64: define{{.*}} void @ParamPassing2(i127 %{{.+}}, i63 signext %{{.+}}) // PPC32: define{{.*}} void @ParamPassing2(ptr byval(i128) align 8 %{{.+}}, i63 %{{.+}}) // AARCH64: define{{.*}} void @ParamPassing2(i127 %{{.+}}, i63 %{{.+}}) // AARCH64DARWIN: define{{.*}} void @ParamPassing2(i127 %{{.+}}, i63 %{{.+}}) // ARM: define{{.*}} arm_aapcscc void @ParamPassing2(ptr byval(i128) align 8 %{{.+}}, i63 %{{.+}}) // LA64: define{{.*}} void @ParamPassing2(i127 %{{.+}}, i63 signext %{{.+}}) -// LA32: define{{.*}} void @ParamPassing2(ptr %{{.+}}, i63 %{{.+}}) +// LA32: define{{.*}} void @ParamPassing2(ptr dead_on_return %{{.+}}, i63 %{{.+}}) // Make sure we follow the signext rules for promotable integer types. void ParamPassing3(_BitInt(15) a, _BitInt(31) b) {} @@ -129,10 +129,10 @@ void ParamPassing3(_BitInt(15) a, _BitInt(31) b) {} // _BitInt widths to alert us to enable the test. void ParamPassing4(_BitInt(129) a) {} // LIN64: define{{.*}} void @ParamPassing4(ptr byval([24 x i8]) align 8 %{{.+}}) -// WIN64: define dso_local void @ParamPassing4(ptr %{{.+}}) -// LIN32: define{{.*}} void @ParamPassing4(ptr %{{.+}}) -// WIN32: define dso_local void @ParamPassing4(ptr %{{.+}}) -// AARCH64: define{{.*}} void @ParamPassing4(ptr %{{.+}}) +// WIN64: define dso_local void @ParamPassing4(ptr dead_on_return %{{.+}}) +// LIN32: define{{.*}} void @ParamPassing4(ptr dead_on_return %{{.+}}) +// WIN32: define dso_local void @ParamPassing4(ptr dead_on_return %{{.+}}) +// AARCH64: define{{.*}} void @ParamPassing4(ptr dead_on_return %{{.+}}) // NVPTX64-NOT: define{{.*}} void @ParamPassing4(ptr byval(i129) align 8 %{{.+}}) // NVPTX-NOT: define{{.*}} void @ParamPassing4(ptr byval(i129) align 8 %{{.+}}) // SPARCV9-NOT: define{{.*}} void @ParamPassing4(ptr %{{.+}}) @@ -154,8 +154,8 @@ void ParamPassing4(_BitInt(129) a) {} // PPC32-NOT: define{{.*}} void @ParamPassing4(ptr byval(i129) align 8 %{{.+}}) // AARCH64DARWIN-NOT: define{{.*}} void @ParamPassing4(ptr byval(i129) align 8 %{{.+}}) // ARM-NOT: define{{.*}} arm_aapcscc void @ParamPassing4(ptr byval(i129) align 8 %{{.+}}) -// LA64: define{{.*}} void @ParamPassing4(ptr %{{.+}}) -// LA32: define{{.*}} void @ParamPassing4(ptr %{{.+}}) +// LA64: define{{.*}} void @ParamPassing4(ptr dead_on_return %{{.+}}) +// LA32: define{{.*}} void @ParamPassing4(ptr dead_on_return %{{.+}}) #endif _BitInt(63) ReturnPassing(void) { return 0; } @@ -251,7 +251,7 @@ _BitInt(127) ReturnPassing3(void) { return 0; } // LA32: define{{.*}} void @ReturnPassing3(ptr dead_on_unwind noalias writable sret _BitInt(128) ReturnPassing4(void) { return 0; } -// LIN64: define{{.*}} { i64, i64 } @ReturnPassing4( +// LIN64: define{{.*}} i128 @ReturnPassing4( // WIN64: define dso_local void @ReturnPassing4(ptr dead_on_unwind noalias writable sret // LIN32: define{{.*}} void @ReturnPassing4(ptr dead_on_unwind noalias writable sret // WIN32: define dso_local void @ReturnPassing4(ptr dead_on_unwind noalias writable sret diff --git a/clang/test/CodeGen/extend-arg-64.c b/clang/test/CodeGen/extend-arg-64.c index 2cb56d35af21d..8b99c01807ecc 100644 --- a/clang/test/CodeGen/extend-arg-64.c +++ b/clang/test/CodeGen/extend-arg-64.c @@ -84,7 +84,7 @@ int test(void) { #ifdef D128 knr(i128); // CHECKEXT: load i128 - // CHECKEXT: call{{.*}} void (i64, i64, ...) @knr + // CHECKEXT: call{{.*}} void (i128, ...) @knr #endif knr(u32, s32, u16, s16, u8, s8); diff --git a/clang/test/CodeGen/isfpclass.c b/clang/test/CodeGen/isfpclass.c index 26dd846a2bf20..ee3a22b40fefd 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 writable writeonly sret(<4 x i64>) align 16 captures(none) initializes((0, 32)) [[AGG_RESULT:%.*]], ptr noundef readonly captures(none) [[TMP0:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] { +// CHECK-SAME: (ptr dead_on_unwind noalias writable writeonly sret(<4 x i64>) align 16 captures(none) initializes((0, 32)) [[AGG_RESULT:%.*]], ptr dead_on_return noundef readonly captures(none) [[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/math-libcalls-tbaa-indirect-args.c b/clang/test/CodeGen/math-libcalls-tbaa-indirect-args.c index eb706154300a2..0124cc5c06d43 100644 --- a/clang/test/CodeGen/math-libcalls-tbaa-indirect-args.c +++ b/clang/test/CodeGen/math-libcalls-tbaa-indirect-args.c @@ -30,37 +30,37 @@ long double powl(long double a, long double b); // // CHECK-PPC-LABEL: define dso_local ppc_fp128 @test_powl( // CHECK-PPC-SAME: ppc_fp128 noundef [[A:%.*]], ppc_fp128 noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { -// CHECK-PPC: [[CALL:%.*]] = tail call ppc_fp128 @powl(ppc_fp128 noundef [[A]], ppc_fp128 noundef [[B]]) #[[ATTR3:[0-9]+]], !tbaa [[TBAA2:![0-9]+]] +// CHECK-PPC: [[CALL:%.*]] = tail call ppc_fp128 @powl(ppc_fp128 noundef [[A]], ppc_fp128 noundef [[B]]) #[[ATTR4:[0-9]+]], !tbaa [[TBAA2:![0-9]+]] // // CHECK-ARM-LABEL: define dso_local double @test_powl( // CHECK-ARM-SAME: double noundef [[A:%.*]], double noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { -// CHECK-ARM: [[CALL:%.*]] = tail call double @powl(double noundef [[A]], double noundef [[B]]) #[[ATTR2:[0-9]+]], !tbaa [[TBAA3:![0-9]+]] +// CHECK-ARM: [[CALL:%.*]] = tail call double @powl(double noundef [[A]], double noundef [[B]]) #[[ATTR3:[0-9]+]], !tbaa [[TBAA3:![0-9]+]] // // CHECK-ARM-HF-LABEL: define dso_local double @test_powl( // CHECK-ARM-HF-SAME: double noundef [[A:%.*]], double noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { -// CHECK-ARM-HF: [[CALL:%.*]] = tail call double @powl(double noundef [[A]], double noundef [[B]]) #[[ATTR2:[0-9]+]], !tbaa [[TBAA3:![0-9]+]] +// CHECK-ARM-HF: [[CALL:%.*]] = tail call double @powl(double noundef [[A]], double noundef [[B]]) #[[ATTR3:[0-9]+]], !tbaa [[TBAA3:![0-9]+]] // // CHECK-THUMB-LABEL: define double @test_powl( // CHECK-THUMB-SAME: double noundef [[A:%.*]], double noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { -// CHECK-THUMB: [[CALL:%.*]] = tail call double @powl(double noundef [[A]], double noundef [[B]]) #[[ATTR2:[0-9]+]], !tbaa [[TBAA3:![0-9]+]] +// CHECK-THUMB: [[CALL:%.*]] = tail call double @powl(double noundef [[A]], double noundef [[B]]) #[[ATTR3:[0-9]+]], !tbaa [[TBAA3:![0-9]+]] // // CHECK-AARCH-LABEL: define dso_local fp128 @test_powl( // CHECK-AARCH-SAME: fp128 noundef [[A:%.*]], fp128 noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { -// CHECK-AARCH: [[CALL:%.*]] = tail call fp128 @powl(fp128 noundef [[A]], fp128 noundef [[B]]) #[[ATTR2:[0-9]+]], !tbaa [[TBAA2:![0-9]+]] +// CHECK-AARCH: [[CALL:%.*]] = tail call fp128 @powl(fp128 noundef [[A]], fp128 noundef [[B]]) #[[ATTR3:[0-9]+]], !tbaa [[TBAA2:![0-9]+]] // // CHECK-SPIR-LABEL: define dso_local spir_func double @test_powl( // CHECK-SPIR-SAME: double noundef [[A:%.*]], double noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { -// CHECK-SPIR: [[CALL:%.*]] = tail call spir_func double @powl(double noundef [[A]], double noundef [[B]]) #[[ATTR3:[0-9]+]], !tbaa [[TBAA2:![0-9]+]] +// CHECK-SPIR: [[CALL:%.*]] = tail call spir_func double @powl(double noundef [[A]], double noundef [[B]]) #[[ATTR4:[0-9]+]], !tbaa [[TBAA2:![0-9]+]] // // CHECK-MINGW32-LABEL: define dso_local void @test_powl( -// CHECK-MINGW32-SAME: ptr dead_on_unwind noalias writable writeonly sret(x86_fp80) align 16 captures(none) initializes((0, 10)) [[AGG_RESULT:%.*]], ptr noundef readonly captures(none) [[TMP0:%.*]], ptr noundef readonly captures(none) [[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]] -// CHECK-MINGW32: store x86_fp80 [[B]], ptr [[BYVAL_TEMP1:%.*]], align 16, !tbaa [[TBAA3]] -// CHECK-MINGW32: call void @powl(ptr dead_on_unwind nonnull writable sret(x86_fp80) align 16 [[TMP:%.*]], ptr noundef nonnull [[BYVAL_TEMP]], ptr noundef nonnull [[BYVAL_TEMP1]]) #[[ATTR3:[0-9]+]] -// CHECK-MINGW32: [[TMP2:%.*]] = load x86_fp80, ptr [[TMP]], align 16, !tbaa [[TBAA3]] -// CHECK-MINGW32: store x86_fp80 [[TMP2]], ptr [[AGG_RESULT]], align 16, !tbaa [[TBAA3]] +// CHECK-MINGW32-SAME: ptr dead_on_unwind noalias writable writeonly sret(x86_fp80) align 16 captures(none) initializes((0, 10)) [[AGG_RESULT:%.*]], ptr dead_on_return noundef readonly captures(none) [[TMP0:%.*]], ptr dead_on_return noundef readonly captures(none) [[TMP1:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-MINGW32: [[A:%.*]] = load x86_fp80, ptr [[TMP0]], align 16, !tbaa [[TBAA6:![0-9]+]] +// CHECK-MINGW32: [[B:%.*]] = load x86_fp80, ptr [[TMP1]], align 16, !tbaa [[TBAA6]] +// CHECK-MINGW32: store x86_fp80 [[A]], ptr [[BYVAL_TEMP:%.*]], align 16, !tbaa [[TBAA6]] +// CHECK-MINGW32: store x86_fp80 [[B]], ptr [[BYVAL_TEMP1:%.*]], align 16, !tbaa [[TBAA6]] +// CHECK-MINGW32: call void @powl(ptr dead_on_unwind nonnull writable sret(x86_fp80) align 16 [[TMP:%.*]], ptr dead_on_return noundef nonnull [[BYVAL_TEMP]], ptr dead_on_return noundef nonnull [[BYVAL_TEMP1]]) #[[ATTR3:[0-9]+]] +// CHECK-MINGW32: [[TMP2:%.*]] = load x86_fp80, ptr [[TMP]], align 16, !tbaa [[TBAA6]] +// CHECK-MINGW32: store x86_fp80 [[TMP2]], ptr [[AGG_RESULT]], align 16, !tbaa [[TBAA6]] // long double test_powl(long double a, long double b) { return powl(a, b); @@ -93,51 +93,51 @@ 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 writable writeonly sret({ ppc_fp128, ppc_fp128 }) align 16 captures(none) initializes((0, 32)) [[AGG_RESULT:%.*]], ptr noundef readonly byval({ ppc_fp128, ppc_fp128 }) align 16 captures(none) [[CLD:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { +// CHECK-PPC-SAME: ptr dead_on_unwind noalias writable writeonly sret({ ppc_fp128, ppc_fp128 }) align 16 captures(none) initializes((0, 32)) [[AGG_RESULT:%.*]], ptr noundef readonly byval({ ppc_fp128, ppc_fp128 }) align 16 captures(none) [[CLD:%.*]]) local_unnamed_addr #[[ATTR2:[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 // CHECK-PPC: store ppc_fp128 [[CLD_IMAG]], ptr [[BYVAL_TEMP_IMAGP:%.*]], align 16 -// CHECK-PPC: [[CALL:%.*]] = tail call ppc_fp128 @cargl(ptr noundef nonnull byval({ ppc_fp128, ppc_fp128 }) align 16 [[BYVAL_TEMP]]) #[[ATTR3]] +// CHECK-PPC: [[CALL:%.*]] = tail call ppc_fp128 @cargl(ptr noundef nonnull byval({ ppc_fp128, ppc_fp128 }) align 16 [[BYVAL_TEMP]]) #[[ATTR4]] // CHECK-PPC: store ppc_fp128 [[MUL_RL:%.*]], ptr [[AGG_RESULT]], align 16 // 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 writable writeonly sret({ double, double }) align 8 captures(none) 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-SAME: ptr dead_on_unwind noalias writable writeonly sret({ double, double }) align 8 captures(none) initializes((0, 16)) [[AGG_RESULT:%.*]], [2 x i64] noundef [[CLD_COERCE:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { +// CHECK-ARM: [[CALL:%.*]] = tail call double @cargl([2 x i64] noundef [[CLD_COERCE]]) #[[ATTR3]], !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 // // CHECK-ARM-HF-LABEL: define dso_local { double, double } @test_cargl( -// CHECK-ARM-HF-SAME: { double, double } noundef [[CLD_COERCE:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { -// CHECK-ARM-HF: [[CALL:%.*]] = tail call double @cargl({ double, double } noundef [[CLD_COERCE]]) #[[ATTR2]], !tbaa [[TBAA3]] +// CHECK-ARM-HF-SAME: { double, double } noundef [[CLD_COERCE:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { +// CHECK-ARM-HF: [[CALL:%.*]] = tail call double @cargl({ double, double } noundef [[CLD_COERCE]]) #[[ATTR3]], !tbaa [[TBAA3]] // // CHECK-THUMB-LABEL: define { double, double } @test_cargl( -// CHECK-THUMB-SAME: [2 x double] noundef [[CLD_COERCE:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { -// CHECK-THUMB: [[CALL:%.*]] = tail call double @cargl([2 x double] noundef [[CLD_COERCE]]) #[[ATTR2]], !tbaa [[TBAA3]] +// CHECK-THUMB-SAME: [2 x double] noundef [[CLD_COERCE:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { +// CHECK-THUMB: [[CALL:%.*]] = tail call double @cargl([2 x double] noundef [[CLD_COERCE]]) #[[ATTR3]], !tbaa [[TBAA3]] // // CHECK-AARCH-LABEL: define dso_local { fp128, fp128 } @test_cargl( -// CHECK-AARCH-SAME: [2 x fp128] noundef alignstack(16) [[CLD_COERCE:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { -// CHECK-AARCH: [[CALL:%.*]] = tail call fp128 @cargl([2 x fp128] noundef alignstack(16) [[CLD_COERCE]]) #[[ATTR2]], !tbaa [[TBAA2]] +// CHECK-AARCH-SAME: [2 x fp128] noundef alignstack(16) [[CLD_COERCE:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { +// CHECK-AARCH: [[CALL:%.*]] = tail call fp128 @cargl([2 x fp128] noundef alignstack(16) [[CLD_COERCE]]) #[[ATTR3]], !tbaa [[TBAA2]] // // CHECK-SPIR-LABEL: define dso_local spir_func void @test_cargl( -// CHECK-SPIR-SAME: ptr dead_on_unwind noalias writable writeonly sret({ double, double }) align 8 captures(none) initializes((0, 16)) [[AGG_RESULT:%.*]], ptr noundef readonly byval({ double, double }) align 8 captures(none) [[CLD:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { +// CHECK-SPIR-SAME: ptr dead_on_unwind noalias writable writeonly sret({ double, double }) align 8 captures(none) initializes((0, 16)) [[AGG_RESULT:%.*]], ptr noundef readonly byval({ double, double }) align 8 captures(none) [[CLD:%.*]]) local_unnamed_addr #[[ATTR2:[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 // CHECK-SPIR: store double [[CLD_IMAG]], ptr [[BYVAL_TEMP_IMAGP:%.*]], align 8 -// CHECK-SPIR: [[CALL:%.*]] = tail call spir_func double @cargl(ptr noundef nonnull byval({ double, double }) align 8 [[BYVAL_TEMP]]) #[[ATTR3]] +// CHECK-SPIR: [[CALL:%.*]] = tail call spir_func double @cargl(ptr noundef nonnull byval({ double, double }) align 8 [[BYVAL_TEMP]]) #[[ATTR4]] // CHECK-SPIR: store double [[MUL_RL:%.*]], ptr [[AGG_RESULT]], align 8 // 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 writable writeonly sret({ x86_fp80, x86_fp80 }) align 16 captures(none) initializes((0, 10), (16, 26)) [[AGG_RESULT:%.*]], ptr noundef readonly captures(none) [[CLD:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-MINGW32-SAME: ptr dead_on_unwind noalias writable writeonly sret({ x86_fp80, x86_fp80 }) align 16 captures(none) initializes((0, 10), (16, 26)) [[AGG_RESULT:%.*]], ptr dead_on_return noundef readonly captures(none) [[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 // CHECK-MINGW32: store x86_fp80 [[CLD_IMAG]], ptr [[BYVAL_TEMP_IMAGP:%.*]], align 16 -// CHECK-MINGW32: call void @cargl(ptr dead_on_unwind nonnull writable sret(x86_fp80) align 16 [[TMP:%.*]], ptr noundef nonnull [[BYVAL_TEMP]]) #[[ATTR3]] -// CHECK-MINGW32: [[TMP0:%.*]] = load x86_fp80, ptr [[TMP]], align 16, !tbaa [[TBAA3]] +// CHECK-MINGW32: call void @cargl(ptr dead_on_unwind nonnull writable sret(x86_fp80) align 16 [[TMP:%.*]], ptr dead_on_return noundef nonnull [[BYVAL_TEMP]]) #[[ATTR3]] +// CHECK-MINGW32: [[TMP0:%.*]] = load x86_fp80, ptr [[TMP]], align 16, !tbaa [[TBAA6]] // CHECK-MINGW32: [[CLD_REAL3:%.*]] = load x86_fp80, ptr [[CLD]], align 16 // CHECK-MINGW32: [[CLD_IMAG5:%.*]] = load x86_fp80, ptr [[CLD_IMAGP]], align 16 // CHECK-MINGW32: store x86_fp80 [[MUL_RL:%.*]], ptr [[AGG_RESULT]], align 16 @@ -166,33 +166,33 @@ int ilogbl(long double a); // // CHECK-PPC-LABEL: define dso_local i32 @test_ilogb( // CHECK-PPC-SAME: ppc_fp128 noundef [[A:%.*]]) local_unnamed_addr #[[ATTR0]] { -// CHECK-PPC: [[CALL:%.*]] = tail call i32 @ilogbl(ppc_fp128 noundef [[A]]) #[[ATTR3]], !tbaa [[TBAA2]] +// CHECK-PPC: [[CALL:%.*]] = tail call i32 @ilogbl(ppc_fp128 noundef [[A]]) #[[ATTR4]], !tbaa [[TBAA2]] // // CHECK-ARM-LABEL: define dso_local i32 @test_ilogb( // CHECK-ARM-SAME: double noundef [[A:%.*]]) local_unnamed_addr #[[ATTR0]] { -// CHECK-ARM: [[CALL:%.*]] = tail call i32 @ilogbl(double noundef [[A]]) #[[ATTR2]], !tbaa [[TBAA3]] +// CHECK-ARM: [[CALL:%.*]] = tail call i32 @ilogbl(double noundef [[A]]) #[[ATTR3]], !tbaa [[TBAA3]] // // CHECK-ARM-HF-LABEL: define dso_local i32 @test_ilogb( // CHECK-ARM-HF-SAME: double noundef [[A:%.*]]) local_unnamed_addr #[[ATTR0]] { -// CHECK-ARM-HF: [[CALL:%.*]] = tail call i32 @ilogbl(double noundef [[A]]) #[[ATTR2]], !tbaa [[TBAA3]] +// CHECK-ARM-HF: [[CALL:%.*]] = tail call i32 @ilogbl(double noundef [[A]]) #[[ATTR3]], !tbaa [[TBAA3]] // // CHECK-THUMB-LABEL: define i32 @test_ilogb( // CHECK-THUMB-SAME: double noundef [[A:%.*]]) local_unnamed_addr #[[ATTR0]] { -// CHECK-THUMB: [[CALL:%.*]] = tail call i32 @ilogbl(double noundef [[A]]) #[[ATTR2]], !tbaa [[TBAA3]] +// CHECK-THUMB: [[CALL:%.*]] = tail call i32 @ilogbl(double noundef [[A]]) #[[ATTR3]], !tbaa [[TBAA3]] // // CHECK-AARCH-LABEL: define dso_local i32 @test_ilogb( // CHECK-AARCH-SAME: fp128 noundef [[A:%.*]]) local_unnamed_addr #[[ATTR0]] { -// CHECK-AARCH: [[CALL:%.*]] = tail call i32 @ilogbl(fp128 noundef [[A]]) #[[ATTR2]], !tbaa [[TBAA2]] +// CHECK-AARCH: [[CALL:%.*]] = tail call i32 @ilogbl(fp128 noundef [[A]]) #[[ATTR3]], !tbaa [[TBAA2]] // // CHECK-SPIR-LABEL: define dso_local spir_func i32 @test_ilogb( // CHECK-SPIR-SAME: double noundef [[A:%.*]]) local_unnamed_addr #[[ATTR0]] { -// CHECK-SPIR: [[CALL:%.*]] = tail call spir_func i32 @ilogbl(double noundef [[A]]) #[[ATTR3]], !tbaa [[TBAA2]] +// CHECK-SPIR: [[CALL:%.*]] = tail call spir_func i32 @ilogbl(double noundef [[A]]) #[[ATTR4]], !tbaa [[TBAA2]] // // CHECK-MINGW32-LABEL: define dso_local i32 @test_ilogb( -// CHECK-MINGW32-SAME: ptr noundef readonly captures(none) [[TMP0:%.*]]) local_unnamed_addr #[[ATTR0]] { -// CHECK-MINGW32: [[A:%.*]] = load x86_fp80, ptr [[TMP0]], align 16, !tbaa [[TBAA3]] -// CHECK-MINGW32: store x86_fp80 [[A]], ptr [[BYVAL_TEMP:%.*]], align 16, !tbaa [[TBAA3]] -// CHECK-MINGW32: [[CALL:%.*]] = call i32 @ilogbl(ptr noundef nonnull [[BYVAL_TEMP]]) #[[ATTR3]] +// CHECK-MINGW32-SAME: ptr dead_on_return noundef readonly captures(none) [[TMP0:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-MINGW32: [[A:%.*]] = load x86_fp80, ptr [[TMP0]], align 16, !tbaa [[TBAA6]] +// CHECK-MINGW32: store x86_fp80 [[A]], ptr [[BYVAL_TEMP:%.*]], align 16, !tbaa [[TBAA6]] +// CHECK-MINGW32: [[CALL:%.*]] = call i32 @ilogbl(ptr dead_on_return noundef nonnull [[BYVAL_TEMP]]) #[[ATTR3]] // int test_ilogb(long double a) { return ilogbl(a); @@ -243,8 +243,8 @@ int test_ilogb(long double a) { // CHECK-SPIR: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0} // CHECK-SPIR: [[META5]] = !{!"Simple C/C++ TBAA"} //. -// CHECK-MINGW32: [[TBAA3]] = !{[[META4:![0-9]+]], [[META4]], i64 0} -// CHECK-MINGW32: [[META4]] = !{!"long double", [[META5:![0-9]+]], i64 0} -// CHECK-MINGW32: [[META5]] = !{!"omnipotent char", [[META6:![0-9]+]], i64 0} -// CHECK-MINGW32: [[META6]] = !{!"Simple C/C++ TBAA"} +// CHECK-MINGW32: [[TBAA6]] = !{[[META7:![0-9]+]], [[META7]], i64 0} +// CHECK-MINGW32: [[META7]] = !{!"long double", [[META8:![0-9]+]], i64 0} +// CHECK-MINGW32: [[META8]] = !{!"omnipotent char", [[META9:![0-9]+]], i64 0} +// CHECK-MINGW32: [[META9]] = !{!"Simple C/C++ TBAA"} //. diff --git a/clang/test/CodeGen/mingw-long-double.c b/clang/test/CodeGen/mingw-long-double.c index 0fc8f01509682..b98929701bc62 100644 --- a/clang/test/CodeGen/mingw-long-double.c +++ b/clang/test/CodeGen/mingw-long-double.c @@ -29,15 +29,15 @@ long double TestLD(long double x) { return x * x; } // GNU32: define dso_local x86_fp80 @TestLD(x86_fp80 noundef %x) -// GNU64: define dso_local void @TestLD(ptr dead_on_unwind noalias writable sret(x86_fp80) align 16 %agg.result, ptr noundef %0) +// GNU64: define dso_local void @TestLD(ptr dead_on_unwind noalias writable sret(x86_fp80) align 16 %agg.result, ptr dead_on_return noundef %0) // MSC64: define dso_local double @TestLD(double noundef %x) long double _Complex TestLDC(long double _Complex x) { return x * x; } // GNU32: define dso_local void @TestLDC(ptr dead_on_unwind noalias writable sret({ x86_fp80, x86_fp80 }) align 4 %agg.result, ptr noundef byval({ x86_fp80, x86_fp80 }) align 4 %x) -// GNU64: define dso_local void @TestLDC(ptr dead_on_unwind noalias writable sret({ x86_fp80, x86_fp80 }) align 16 %agg.result, ptr noundef %x) -// MSC64: define dso_local void @TestLDC(ptr dead_on_unwind noalias writable sret({ double, double }) align 8 %agg.result, ptr noundef %x) +// GNU64: define dso_local void @TestLDC(ptr dead_on_unwind noalias writable sret({ x86_fp80, x86_fp80 }) align 16 %agg.result, ptr dead_on_return noundef %x) +// MSC64: define dso_local void @TestLDC(ptr dead_on_unwind noalias writable sret({ double, double }) align 8 %agg.result, ptr dead_on_return noundef %x) // GNU32: declare dso_local void @__mulxc3 // GNU64: declare dso_local void @__mulxc3 diff --git a/clang/test/CodeGen/ms_abi.c b/clang/test/CodeGen/ms_abi.c index 528e546f315d5..5d58c9816da78 100644 --- a/clang/test/CodeGen/ms_abi.c +++ b/clang/test/CodeGen/ms_abi.c @@ -142,7 +142,7 @@ struct i128 { }; __attribute__((ms_abi)) struct i128 f7(struct i128 a) { - // WIN64: define dso_local void @f7(ptr dead_on_unwind noalias writable sret(%struct.i128) align 8 %agg.result, ptr noundef %a) - // FREEBSD: define{{.*}} win64cc void @f7(ptr dead_on_unwind noalias writable sret(%struct.i128) align 8 %agg.result, ptr noundef %a) + // WIN64: define dso_local void @f7(ptr dead_on_unwind noalias writable sret(%struct.i128) align 8 %agg.result, ptr dead_on_return noundef %a) + // FREEBSD: define{{.*}} win64cc void @f7(ptr dead_on_unwind noalias writable sret(%struct.i128) align 8 %agg.result, ptr dead_on_return noundef %a) return a; } diff --git a/clang/test/CodeGen/new-pass-manager-opt-bisect.c b/clang/test/CodeGen/new-pass-manager-opt-bisect.c index 91a0adf252bb5..5d5fdd473422a 100644 --- a/clang/test/CodeGen/new-pass-manager-opt-bisect.c +++ b/clang/test/CodeGen/new-pass-manager-opt-bisect.c @@ -7,6 +7,6 @@ // CHECK: BISECT: running pass (1) // CHECK-NOT: BISECT: running pass (1) // Make sure that legacy pass manager is running -// CHECK: Instruction Selection +// CHECK: -isel int func(int a) { return a; } diff --git a/clang/test/CodeGen/null-sanitizer-debug-info-regression.cpp b/clang/test/CodeGen/null-sanitizer-debug-info-regression.cpp new file mode 100644 index 0000000000000..0b62f24177bbd --- /dev/null +++ b/clang/test/CodeGen/null-sanitizer-debug-info-regression.cpp @@ -0,0 +1,5 @@ +// RUN: %clangxx -g -fsanitize=null -fsanitize-trap=all -fsanitize-annotate-debug-info=all -O2 -std=c++17 -c -o /dev/null %s + +struct foo { + foo(int, long, const int & = int()); +} foo(0, 0); diff --git a/clang/test/CodeGen/pass-by-value-noalias.c b/clang/test/CodeGen/pass-by-value-noalias.c index bc35d13c4df6a..e673ceb80bebe 100644 --- a/clang/test/CodeGen/pass-by-value-noalias.c +++ b/clang/test/CodeGen/pass-by-value-noalias.c @@ -11,6 +11,6 @@ struct Foo { int f; }; -// WITH_NOALIAS: define{{.*}} void @take(ptr noalias noundef %arg) -// NO_NOALIAS: define{{.*}} void @take(ptr noundef %arg) +// WITH_NOALIAS: define{{.*}} void @take(ptr dead_on_return noalias noundef %arg) +// NO_NOALIAS: define{{.*}} void @take(ptr dead_on_return noundef %arg) void take(struct Foo arg) {} diff --git a/clang/test/CodeGen/ptrauth-in-c-struct.c b/clang/test/CodeGen/ptrauth-in-c-struct.c index 2aec31ec3baf9..c74be17b4c837 100644 --- a/clang/test/CodeGen/ptrauth-in-c-struct.c +++ b/clang/test/CodeGen/ptrauth-in-c-struct.c @@ -115,7 +115,7 @@ void test_move_assignment_SA(SA *p) { *p = getSA(); } -// CHECK: define void @test_parameter_SA(ptr noundef %{{.*}}) +// CHECK: define void @test_parameter_SA(ptr dead_on_return noundef %{{.*}}) // CHECK-NOT: call // CHECK: ret void @@ -128,7 +128,7 @@ void test_parameter_SA(SA a) { // CHECK: store ptr %[[A]], ptr %[[A_ADDR]], align 8 // CHECK: %[[V0:.*]] = load ptr, ptr %[[A_ADDR]], align 8 // CHECK: call void @__copy_constructor_8_8_t0w4_pa1_50_8(ptr %[[AGG_TMP]], ptr %[[V0]]) -// CHECK: call void @calleeSA(ptr noundef %[[AGG_TMP]]) +// CHECK: call void @calleeSA(ptr dead_on_return noundef %[[AGG_TMP]]) // CHECK-NOT: call // CHECK: ret void diff --git a/clang/test/CodeGen/regcall.c b/clang/test/CodeGen/regcall.c index f10da87353fa1..d4b9f00d54d41 100644 --- a/clang/test/CodeGen/regcall.c +++ b/clang/test/CodeGen/regcall.c @@ -28,7 +28,7 @@ struct Large { int a[5]; }; void __regcall v4(int a, struct Large b, int c) {} // Win32: define dso_local x86_regcallcc void @__regcall3__v4(i32 inreg noundef %a, ptr noundef byval(%struct.Large) align 4 %b, i32 inreg noundef %c) // Lin32: define dso_local x86_regcallcc void @__regcall3__v4(i32 inreg noundef %a, ptr noundef byval(%struct.Large) align 4 %b, i32 noundef %c) -// Win64: define dso_local x86_regcallcc void @__regcall3__v4(i32 noundef %a, ptr noundef %b, i32 noundef %c) +// Win64: define dso_local x86_regcallcc void @__regcall3__v4(i32 noundef %a, ptr dead_on_return noundef %b, i32 noundef %c) // Lin64: define dso_local x86_regcallcc void @__regcall3__v4(i32 noundef %a, [5 x i32] %b.coerce, i32 noundef %c) void __regcall v5(long long a, int b, int c) {} @@ -47,7 +47,7 @@ void __regcall hfa1(int a, struct HFA4 b, int c) {} // indirectly. Additional vector arguments can consume the rest of the SSE // registers. void __regcall hfa2(struct HFA4 a, struct HFA4 b, double c) {} -// X86: define dso_local x86_regcallcc void @__regcall3__hfa2(double %a.0, double %a.1, double %a.2, double %a.3, double %b.0, double %b.1, double %b.2, double %b.3, ptr inreg noundef %0) +// X86: define dso_local x86_regcallcc void @__regcall3__hfa2(double %a.0, double %a.1, double %a.2, double %a.3, double %b.0, double %b.1, double %b.2, double %b.3, ptr dead_on_return inreg noundef %0) // X64: define dso_local x86_regcallcc void @__regcall3__hfa2(double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double noundef %c) // Ensure that we pass builtin types directly while counting them against the @@ -61,7 +61,7 @@ void __regcall hfa3(double a, double b, double c, double d, double e, struct HFA // handling to ensure alignment. void __regcall hfa4(struct HFA5 a) {} // X32: define dso_local x86_regcallcc void @__regcall3__hfa4(ptr noundef byval(%struct.HFA5) align 4 %{{.*}}) -// Win64: define dso_local x86_regcallcc void @__regcall3__hfa4(ptr noundef %a) +// Win64: define dso_local x86_regcallcc void @__regcall3__hfa4(ptr dead_on_return noundef %a) // Lin64: define dso_local x86_regcallcc void @__regcall3__hfa4(double %a.coerce0, double %a.coerce1, double %a.coerce2, double %a.coerce3, double %a.coerce4) // Return HFAs of 4 or fewer elements in registers. @@ -79,7 +79,7 @@ void __regcall hva1(int a, struct HVA4 b, int c) {} // X64: define dso_local x86_regcallcc void @__regcall3__hva1(i32 noundef %a, <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i32 noundef %c) void __regcall hva2(struct HVA4 a, struct HVA4 b, v4f32 c) {} -// X86: define dso_local x86_regcallcc void @__regcall3__hva2(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, ptr inreg noundef %0) +// X86: define dso_local x86_regcallcc void @__regcall3__hva2(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, ptr dead_on_return inreg noundef %0) // X64: define dso_local x86_regcallcc void @__regcall3__hva2(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> noundef %c) void __regcall hva3(v4f32 a, v4f32 b, v4f32 c, v4f32 d, v4f32 e, struct HVA2 f) {} @@ -95,6 +95,6 @@ void __regcall odd_size_hva(struct OddSizeHVA a) {} struct HFA6 { __m128 f[4]; }; struct HFA6 __regcall ret_reg_reused(struct HFA6 a, struct HFA6 b, struct HFA6 c, struct HFA6 d){ struct HFA6 h; return h;} -// X86: define dso_local x86_regcallcc %struct.HFA6 @__regcall3__ret_reg_reused(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, ptr inreg noundef %c, ptr inreg noundef %d) +// X86: define dso_local x86_regcallcc %struct.HFA6 @__regcall3__ret_reg_reused(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, ptr dead_on_return inreg noundef %c, ptr dead_on_return inreg noundef %d) // Win64: define dso_local x86_regcallcc %struct.HFA6 @__regcall3__ret_reg_reused(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, <4 x float> %c.0, <4 x float> %c.1, <4 x float> %c.2, <4 x float> %c.3, <4 x float> %d.0, <4 x float> %d.1, <4 x float> %d.2, <4 x float> %d.3) // Lin64: define dso_local x86_regcallcc %struct.HFA6 @__regcall3__ret_reg_reused([4 x <4 x float>] %a.coerce, [4 x <4 x float>] %b.coerce, [4 x <4 x float>] %c.coerce, [4 x <4 x float>] %d.coerce) diff --git a/clang/test/CodeGen/regcall2.c b/clang/test/CodeGen/regcall2.c index c88d4e485b104..42619369677b2 100644 --- a/clang/test/CodeGen/regcall2.c +++ b/clang/test/CodeGen/regcall2.c @@ -20,7 +20,7 @@ double __regcall bar(__sVector a) { // FIXME: Do we need to change for Windows? // Win: define dso_local x86_regcallcc void @__regcall3__foo(ptr dead_on_unwind noalias writable sret(%struct.__sVector) align 64 %agg.result, i32 noundef %a) #0 -// Win: define dso_local x86_regcallcc double @__regcall3__bar(ptr noundef %a) #0 +// Win: define dso_local x86_regcallcc double @__regcall3__bar(ptr dead_on_return noundef %a) #0 // Win: attributes #0 = { noinline nounwind optnone "min-legal-vector-width"="0" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+avx,+avx2,+avx512f,+avx512vl,+crc32,+cx8,+evex512,+f16c,+fma,+mmx,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave" } // Lin: define dso_local x86_regcallcc %struct.__sVector @__regcall3__foo(i32 noundef %a) #0 diff --git a/clang/test/CodeGen/regcall4.c b/clang/test/CodeGen/regcall4.c index 5fbe77fbc7d76..d5fe5d88a0e8c 100644 --- a/clang/test/CodeGen/regcall4.c +++ b/clang/test/CodeGen/regcall4.c @@ -28,7 +28,7 @@ struct Large { int a[5]; }; void __regcall v4(int a, struct Large b, int c) {} // Win32: define dso_local x86_regcallcc void @__regcall4__v4(i32 inreg noundef %a, ptr noundef byval(%struct.Large) align 4 %b, i32 inreg noundef %c) // Lin32: define dso_local x86_regcallcc void @__regcall4__v4(i32 inreg noundef %a, ptr noundef byval(%struct.Large) align 4 %b, i32 noundef %c) -// Win64: define dso_local x86_regcallcc void @__regcall4__v4(i32 noundef %a, ptr noundef %b, i32 noundef %c) +// Win64: define dso_local x86_regcallcc void @__regcall4__v4(i32 noundef %a, ptr dead_on_return noundef %b, i32 noundef %c) // Lin64: define dso_local x86_regcallcc void @__regcall4__v4(i32 noundef %a, [5 x i32] %b.coerce, i32 noundef %c) void __regcall v5(long long a, int b, int c) {} @@ -47,7 +47,7 @@ void __regcall hfa1(int a, struct HFA4 b, int c) {} // indirectly. Additional vector arguments can consume the rest of the SSE // registers. void __regcall hfa2(struct HFA4 a, struct HFA4 b, double c) {} -// X86: define dso_local x86_regcallcc void @__regcall4__hfa2(double %a.0, double %a.1, double %a.2, double %a.3, double %b.0, double %b.1, double %b.2, double %b.3, ptr inreg noundef %0) +// X86: define dso_local x86_regcallcc void @__regcall4__hfa2(double %a.0, double %a.1, double %a.2, double %a.3, double %b.0, double %b.1, double %b.2, double %b.3, ptr dead_on_return inreg noundef %0) // X64: define dso_local x86_regcallcc void @__regcall4__hfa2(double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double noundef %c) // Ensure that we pass builtin types directly while counting them against the @@ -61,7 +61,7 @@ void __regcall hfa3(double a, double b, double c, double d, double e, struct HFA // handling to ensure alignment. void __regcall hfa4(struct HFA5 a) {} // X32: define dso_local x86_regcallcc void @__regcall4__hfa4(ptr noundef byval(%struct.HFA5) align 4 %{{.*}}) -// Win64: define dso_local x86_regcallcc void @__regcall4__hfa4(ptr noundef %a) +// Win64: define dso_local x86_regcallcc void @__regcall4__hfa4(ptr dead_on_return noundef %a) // Lin64: define dso_local x86_regcallcc void @__regcall4__hfa4(double %a.coerce0, double %a.coerce1, double %a.coerce2, double %a.coerce3, double %a.coerce4) // Return HFAs of 4 or fewer elements in registers. @@ -79,7 +79,7 @@ void __regcall hva1(int a, struct HVA4 b, int c) {} // X64: define dso_local x86_regcallcc void @__regcall4__hva1(i32 noundef %a, <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i32 noundef %c) void __regcall hva2(struct HVA4 a, struct HVA4 b, v4f32 c) {} -// X86: define dso_local x86_regcallcc void @__regcall4__hva2(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, ptr inreg noundef %0) +// X86: define dso_local x86_regcallcc void @__regcall4__hva2(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, ptr dead_on_return inreg noundef %0) // X64: define dso_local x86_regcallcc void @__regcall4__hva2(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> noundef %c) void __regcall hva3(v4f32 a, v4f32 b, v4f32 c, v4f32 d, v4f32 e, struct HVA2 f) {} @@ -95,6 +95,6 @@ void __regcall odd_size_hva(struct OddSizeHVA a) {} struct HFA6 { __m128 f[4]; }; struct HFA6 __regcall ret_reg_reused(struct HFA6 a, struct HFA6 b, struct HFA6 c, struct HFA6 d){ struct HFA6 h; return h;} -// X86: define dso_local x86_regcallcc %struct.HFA6 @__regcall4__ret_reg_reused(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, ptr inreg noundef %c, ptr inreg noundef %d) +// X86: define dso_local x86_regcallcc %struct.HFA6 @__regcall4__ret_reg_reused(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, ptr dead_on_return inreg noundef %c, ptr dead_on_return inreg noundef %d) // Win64: define dso_local x86_regcallcc %struct.HFA6 @__regcall4__ret_reg_reused(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, <4 x float> %c.0, <4 x float> %c.1, <4 x float> %c.2, <4 x float> %c.3, <4 x float> %d.0, <4 x float> %d.1, <4 x float> %d.2, <4 x float> %d.3) // Lin64: define dso_local x86_regcallcc %struct.HFA6 @__regcall4__ret_reg_reused([4 x <4 x float>] %a.coerce, [4 x <4 x float>] %b.coerce, [4 x <4 x float>] %c.coerce, [4 x <4 x float>] %d.coerce) diff --git a/clang/test/CodeGen/sparcv9-abi.c b/clang/test/CodeGen/sparcv9-abi.c index 616e24e7c519d..5a3d64fd37889 100644 --- a/clang/test/CodeGen/sparcv9-abi.c +++ b/clang/test/CodeGen/sparcv9-abi.c @@ -80,7 +80,7 @@ struct medium { int *c, *d; }; -// CHECK-LABEL: define{{.*}} %struct.medium @f_medium(ptr noundef %x) +// CHECK-LABEL: define{{.*}} %struct.medium @f_medium(ptr dead_on_return noundef %x) struct medium f_medium(struct medium x) { x.a += *x.b; x.b = 0; @@ -94,7 +94,7 @@ struct large { int x; }; -// CHECK-LABEL: define{{.*}} void @f_large(ptr dead_on_unwind noalias writable sret(%struct.large) align 8 %agg.result, ptr noundef %x) +// CHECK-LABEL: define{{.*}} void @f_large(ptr dead_on_unwind noalias writable sret(%struct.large) align 8 %agg.result, ptr dead_on_return noundef %x) struct large f_large(struct large x) { x.a += *x.b; x.b = 0; diff --git a/clang/test/CodeGen/vectorcall.c b/clang/test/CodeGen/vectorcall.c index cab7fc0972d7b..09b3310c7c4c8 100644 --- a/clang/test/CodeGen/vectorcall.c +++ b/clang/test/CodeGen/vectorcall.c @@ -17,7 +17,7 @@ void __vectorcall v3(int a, struct Small b, int c) {} struct Large { int a[5]; }; void __vectorcall v4(int a, struct Large b, int c) {} // X86: define dso_local x86_vectorcallcc void @"\01v4@@28"(i32 inreg noundef %a, ptr noundef byval(%struct.Large) align 4 %b, i32 inreg noundef %c) -// X64: define dso_local x86_vectorcallcc void @"\01v4@@40"(i32 noundef %a, ptr noundef %b, i32 noundef %c) +// X64: define dso_local x86_vectorcallcc void @"\01v4@@40"(i32 noundef %a, ptr dead_on_return noundef %b, i32 noundef %c) void __vectorcall v5(long long a, int b, int c) {} // X86: define dso_local x86_vectorcallcc void @"\01v5@@16"(i64 noundef %a, i32 inreg noundef %b, i32 inreg noundef %c) @@ -35,21 +35,21 @@ void __vectorcall hfa1(int a, struct HFA4 b, int c) {} // indirectly. Additional vector arguments can consume the rest of the SSE // registers. void __vectorcall hfa2(struct HFA4 a, struct HFA4 b, double c) {} -// X86: define dso_local x86_vectorcallcc void @"\01hfa2@@72"(%struct.HFA4 inreg %a.coerce, ptr inreg noundef %b, double inreg noundef %c) -// X64: define dso_local x86_vectorcallcc void @"\01hfa2@@72"(%struct.HFA4 inreg %a.coerce, ptr noundef %b, double noundef %c) +// X86: define dso_local x86_vectorcallcc void @"\01hfa2@@72"(%struct.HFA4 inreg %a.coerce, ptr dead_on_return inreg noundef %b, double inreg noundef %c) +// X64: define dso_local x86_vectorcallcc void @"\01hfa2@@72"(%struct.HFA4 inreg %a.coerce, ptr dead_on_return noundef %b, double noundef %c) // Ensure that we pass builtin types directly while counting them against the // SSE register usage. void __vectorcall hfa3(double a, double b, double c, double d, double e, struct HFA2 f) {} -// X86: define dso_local x86_vectorcallcc void @"\01hfa3@@56"(double inreg noundef %a, double inreg noundef %b, double inreg noundef %c, double inreg noundef %d, double inreg noundef %e, ptr inreg noundef %f) -// X64: define dso_local x86_vectorcallcc void @"\01hfa3@@56"(double noundef %a, double noundef %b, double noundef %c, double noundef %d, double noundef %e, ptr noundef %f) +// X86: define dso_local x86_vectorcallcc void @"\01hfa3@@56"(double inreg noundef %a, double inreg noundef %b, double inreg noundef %c, double inreg noundef %d, double inreg noundef %e, ptr dead_on_return inreg noundef %f) +// X64: define dso_local x86_vectorcallcc void @"\01hfa3@@56"(double noundef %a, double noundef %b, double noundef %c, double noundef %d, double noundef %e, ptr dead_on_return noundef %f) // Aggregates with more than four elements are not HFAs and are passed byval. // Because they are not classified as homogeneous, they don't get special // handling to ensure alignment. void __vectorcall hfa4(struct HFA5 a) {} // X86: define dso_local x86_vectorcallcc void @"\01hfa4@@40"(ptr noundef byval(%struct.HFA5) align 4 %0) -// X64: define dso_local x86_vectorcallcc void @"\01hfa4@@40"(ptr noundef %a) +// X64: define dso_local x86_vectorcallcc void @"\01hfa4@@40"(ptr dead_on_return noundef %a) // Return HFAs of 4 or fewer elements in registers. static struct HFA2 g_hfa2; @@ -68,26 +68,26 @@ v4f32 __vectorcall hva1(int a, struct HVA4 b, int c) {return b.w;} // X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva1@@80"(i32 noundef %a, %struct.HVA4 inreg %b.coerce, i32 noundef %c) v4f32 __vectorcall hva2(struct HVA4 a, struct HVA4 b, v4f32 c) {return c;} -// X86: define dso_local x86_vectorcallcc <4 x float> @"\01hva2@@144"(%struct.HVA4 inreg %a.coerce, ptr inreg noundef %b, <4 x float> inreg noundef %c) -// X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva2@@144"(%struct.HVA4 inreg %a.coerce, ptr noundef %b, <4 x float> noundef %c) +// X86: define dso_local x86_vectorcallcc <4 x float> @"\01hva2@@144"(%struct.HVA4 inreg %a.coerce, ptr dead_on_return inreg noundef %b, <4 x float> inreg noundef %c) +// X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva2@@144"(%struct.HVA4 inreg %a.coerce, ptr dead_on_return noundef %b, <4 x float> noundef %c) v4f32 __vectorcall hva3(v4f32 a, v4f32 b, v4f32 c, v4f32 d, v4f32 e, struct HVA2 f) {return f.x;} -// X86: define dso_local x86_vectorcallcc <4 x float> @"\01hva3@@112"(<4 x float> inreg noundef %a, <4 x float> inreg noundef %b, <4 x float> inreg noundef %c, <4 x float> inreg noundef %d, <4 x float> inreg noundef %e, ptr inreg noundef %f) -// X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva3@@112"(<4 x float> noundef %a, <4 x float> noundef %b, <4 x float> noundef %c, <4 x float> noundef %d, <4 x float> noundef %e, ptr noundef %f) +// X86: define dso_local x86_vectorcallcc <4 x float> @"\01hva3@@112"(<4 x float> inreg noundef %a, <4 x float> inreg noundef %b, <4 x float> inreg noundef %c, <4 x float> inreg noundef %d, <4 x float> inreg noundef %e, ptr dead_on_return inreg noundef %f) +// X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva3@@112"(<4 x float> noundef %a, <4 x float> noundef %b, <4 x float> noundef %c, <4 x float> noundef %d, <4 x float> noundef %e, ptr dead_on_return noundef %f) // vector types have higher priority then HVA structures, So vector types are allocated first // and HVAs are allocated if enough registers are available v4f32 __vectorcall hva4(struct HVA4 a, struct HVA2 b, v4f32 c) {return b.y;} -// X86: define dso_local x86_vectorcallcc <4 x float> @"\01hva4@@112"(%struct.HVA4 inreg %a.coerce, ptr inreg noundef %b, <4 x float> inreg noundef %c) -// X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva4@@112"(%struct.HVA4 inreg %a.coerce, ptr noundef %b, <4 x float> noundef %c) +// X86: define dso_local x86_vectorcallcc <4 x float> @"\01hva4@@112"(%struct.HVA4 inreg %a.coerce, ptr dead_on_return inreg noundef %b, <4 x float> inreg noundef %c) +// X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva4@@112"(%struct.HVA4 inreg %a.coerce, ptr dead_on_return noundef %b, <4 x float> noundef %c) v4f32 __vectorcall hva5(struct HVA3 a, struct HVA3 b, v4f32 c, struct HVA2 d) {return d.y;} -// X86: define dso_local x86_vectorcallcc <4 x float> @"\01hva5@@144"(%struct.HVA3 inreg %a.coerce, ptr inreg noundef %b, <4 x float> inreg noundef %c, %struct.HVA2 inreg %d.coerce) -// X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva5@@144"(%struct.HVA3 inreg %a.coerce, ptr noundef %b, <4 x float> noundef %c, %struct.HVA2 inreg %d.coerce) +// X86: define dso_local x86_vectorcallcc <4 x float> @"\01hva5@@144"(%struct.HVA3 inreg %a.coerce, ptr dead_on_return inreg noundef %b, <4 x float> inreg noundef %c, %struct.HVA2 inreg %d.coerce) +// X64: define dso_local x86_vectorcallcc <4 x float> @"\01hva5@@144"(%struct.HVA3 inreg %a.coerce, ptr dead_on_return noundef %b, <4 x float> noundef %c, %struct.HVA2 inreg %d.coerce) struct HVA4 __vectorcall hva6(struct HVA4 a, struct HVA4 b) { return b;} -// X86: define dso_local x86_vectorcallcc %struct.HVA4 @"\01hva6@@128"(%struct.HVA4 inreg %a.coerce, ptr inreg noundef %b) -// X64: define dso_local x86_vectorcallcc %struct.HVA4 @"\01hva6@@128"(%struct.HVA4 inreg %a.coerce, ptr noundef %b) +// X86: define dso_local x86_vectorcallcc %struct.HVA4 @"\01hva6@@128"(%struct.HVA4 inreg %a.coerce, ptr dead_on_return inreg noundef %b) +// X64: define dso_local x86_vectorcallcc %struct.HVA4 @"\01hva6@@128"(%struct.HVA4 inreg %a.coerce, ptr dead_on_return noundef %b) struct HVA5 __vectorcall hva7(void) {struct HVA5 a = {}; return a;} // X86: define dso_local x86_vectorcallcc void @"\01hva7@@0"(ptr dead_on_unwind noalias writable sret(%struct.HVA5) align 16 %agg.result) @@ -108,8 +108,8 @@ void __vectorcall odd_size_hva(struct OddSizeHVA a) {} // consider 'p7' as a register. Instead p5 gets put into the register on the second pass. // x86 should pass p2, p6 and p7 in registers, then p1 in the second pass. struct HFA2 __vectorcall AddParticles(struct HFA2 p1, float p2, struct HFA4 p3, int p4, struct HFA2 p5, float p6, float p7, int p8){ return p1;} -// X86: define dso_local x86_vectorcallcc %struct.HFA2 @"\01AddParticles@@84"(%struct.HFA2 inreg %p1.coerce, float inreg noundef %p2, ptr inreg noundef %p3, i32 inreg noundef %p4, ptr noundef %p5, float inreg noundef %p6, float inreg noundef %p7, i32 noundef %p8) -// X64: define dso_local x86_vectorcallcc %struct.HFA2 @"\01AddParticles@@104"(%struct.HFA2 inreg %p1.coerce, float noundef %p2, ptr noundef %p3, i32 noundef %p4, %struct.HFA2 inreg %p5.coerce, float noundef %p6, float noundef %p7, i32 noundef %p8) +// X86: define dso_local x86_vectorcallcc %struct.HFA2 @"\01AddParticles@@84"(%struct.HFA2 inreg %p1.coerce, float inreg noundef %p2, ptr dead_on_return inreg noundef %p3, i32 inreg noundef %p4, ptr dead_on_return noundef %p5, float inreg noundef %p6, float inreg noundef %p7, i32 noundef %p8) +// X64: define dso_local x86_vectorcallcc %struct.HFA2 @"\01AddParticles@@104"(%struct.HFA2 inreg %p1.coerce, float noundef %p2, ptr dead_on_return noundef %p3, i32 noundef %p4, %struct.HFA2 inreg %p5.coerce, float noundef %p6, float noundef %p7, i32 noundef %p8) // Vectorcall in both architectures allows passing of an HVA as long as there is room, // even if it is not one of the first 6 arguments. First pass puts p4 into a @@ -117,8 +117,8 @@ struct HFA2 __vectorcall AddParticles(struct HFA2 p1, float p2, struct HFA4 p3, // in a register, does NOT put p7 in a register (since there's no room), then puts // p8 in a register. void __vectorcall HVAAnywhere(struct HFA2 p1, int p2, int p3, float p4, int p5, int p6, struct HFA4 p7, struct HFA2 p8, float p9){} -// X86: define dso_local x86_vectorcallcc void @"\01HVAAnywhere@@88"(%struct.HFA2 inreg %p1.coerce, i32 inreg noundef %p2, i32 inreg noundef %p3, float inreg noundef %p4, i32 noundef %p5, i32 noundef %p6, ptr noundef %p7, %struct.HFA2 inreg %p8.coerce, float inreg noundef %p9) -// X64: define dso_local x86_vectorcallcc void @"\01HVAAnywhere@@112"(%struct.HFA2 inreg %p1.coerce, i32 noundef %p2, i32 noundef %p3, float noundef %p4, i32 noundef %p5, i32 noundef %p6, ptr noundef %p7, %struct.HFA2 inreg %p8.coerce, float noundef %p9) +// X86: define dso_local x86_vectorcallcc void @"\01HVAAnywhere@@88"(%struct.HFA2 inreg %p1.coerce, i32 inreg noundef %p2, i32 inreg noundef %p3, float inreg noundef %p4, i32 noundef %p5, i32 noundef %p6, ptr dead_on_return noundef %p7, %struct.HFA2 inreg %p8.coerce, float inreg noundef %p9) +// X64: define dso_local x86_vectorcallcc void @"\01HVAAnywhere@@112"(%struct.HFA2 inreg %p1.coerce, i32 noundef %p2, i32 noundef %p3, float noundef %p4, i32 noundef %p5, i32 noundef %p6, ptr dead_on_return noundef %p7, %struct.HFA2 inreg %p8.coerce, float noundef %p9) #ifndef __x86_64__ // This covers the three ways XMM values can be passed on 32-bit x86: @@ -137,9 +137,9 @@ void __vectorcall vectorcall_indirect_vec( // X86-SAME: double inreg noundef %xmm3, // X86-SAME: double inreg noundef %xmm4, // X86-SAME: <4 x float> inreg noundef %xmm5, -// X86-SAME: ptr inreg noundef %0, +// X86-SAME: ptr dead_on_return inreg noundef %0, // X86-SAME: i32 inreg noundef %edx, -// X86-SAME: ptr noundef %1) +// X86-SAME: ptr dead_on_return noundef %1) void __vectorcall vectorcall_indirect_fp( double xmm0, double xmm1, double xmm2, double xmm3, double xmm4, @@ -153,7 +153,7 @@ void __vectorcall vectorcall_indirect_fp( // X86-SAME: double inreg noundef %xmm3, // X86-SAME: double inreg noundef %xmm4, // X86-SAME: <4 x float> inreg noundef %xmm5, -// X86-SAME: ptr inreg noundef %0, +// X86-SAME: ptr dead_on_return inreg noundef %0, // X86-SAME: i32 inreg noundef %edx, // X86-SAME: double noundef %mem) #endif diff --git a/clang/test/CodeGen/win-fp128.c b/clang/test/CodeGen/win-fp128.c index 328a7aaa7df57..8d223741bc93e 100644 --- a/clang/test/CodeGen/win-fp128.c +++ b/clang/test/CodeGen/win-fp128.c @@ -6,7 +6,7 @@ __float128 fp128_ret(void) { return 0; } // CHECK-GNU64: define dso_local <2 x i64> @fp128_ret() __float128 fp128_args(__float128 a, __float128 b) { return a * b; } -// CHECK-GNU64: define dso_local <2 x i64> @fp128_args(ptr noundef %0, ptr noundef %1) +// CHECK-GNU64: define dso_local <2 x i64> @fp128_args(ptr dead_on_return noundef %0, ptr dead_on_return noundef %1) void fp128_vararg(int a, ...) { // CHECK-GNU64-LABEL: define dso_local void @fp128_vararg diff --git a/clang/test/CodeGen/win64-i128.c b/clang/test/CodeGen/win64-i128.c index e10b2be0530eb..2d83889d8f89b 100644 --- a/clang/test/CodeGen/win64-i128.c +++ b/clang/test/CodeGen/win64-i128.c @@ -12,8 +12,8 @@ int128_t foo(void) { return 0; } int128_t bar(int128_t a, int128_t b) { return a * b; } -// GNU64: define dso_local <2 x i64> @bar(ptr noundef %0, ptr noundef %1) -// MSC64: define dso_local <2 x i64> @bar(ptr noundef %0, ptr noundef %1) +// GNU64: define dso_local <2 x i64> @bar(ptr dead_on_return noundef %0, ptr dead_on_return noundef %1) +// MSC64: define dso_local <2 x i64> @bar(ptr dead_on_return noundef %0, ptr dead_on_return noundef %1) void vararg(int a, ...) { // GNU64-LABEL: define{{.*}} void @vararg diff --git a/clang/test/CodeGen/windows-swiftcall.c b/clang/test/CodeGen/windows-swiftcall.c index 41569c2606622..8716f25b9ddfb 100644 --- a/clang/test/CodeGen/windows-swiftcall.c +++ b/clang/test/CodeGen/windows-swiftcall.c @@ -219,7 +219,7 @@ TEST(struct_big_1) // CHECK-LABEL: define {{.*}} void @return_struct_big_1({{.*}} dead_on_unwind noalias writable sret // Should not be byval. -// CHECK-LABEL: define {{.*}} void @take_struct_big_1(ptr noundef{{( %.*)?}}) +// CHECK-LABEL: define {{.*}} void @take_struct_big_1(ptr dead_on_return noundef{{( %.*)?}}) /*****************************************************************************/ /********************************* TYPE MERGING ******************************/ diff --git a/clang/test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp b/clang/test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp index 152be26948f28..1709c88563267 100644 --- a/clang/test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp +++ b/clang/test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp @@ -576,7 +576,7 @@ void f(__clang_svmfloat8x4_t, __clang_svmfloat8x4_t); // CHECK-NEXT: [[COERCE74_EXTRACT2:%.*]] = extractvalue { , , , } [[COERCE74_TUPLE]], 2 // CHECK-NEXT: [[COERCE74_EXTRACT3:%.*]] = extractvalue { , , , } [[COERCE74_TUPLE]], 3 // CHECK-NEXT: store { , , , } zeroinitializer, ptr [[BYVAL_TEMP]], align 2 -// CHECK-NEXT: call void @_Z1f10svboolx4_tS_( [[COERCE74_EXTRACT0]], [[COERCE74_EXTRACT1]], [[COERCE74_EXTRACT2]], [[COERCE74_EXTRACT3]], ptr noundef [[BYVAL_TEMP]]) +// CHECK-NEXT: call void @_Z1f10svboolx4_tS_( [[COERCE74_EXTRACT0]], [[COERCE74_EXTRACT1]], [[COERCE74_EXTRACT2]], [[COERCE74_EXTRACT3]], ptr dead_on_return noundef [[BYVAL_TEMP]]) // CHECK-NEXT: store { , } zeroinitializer, ptr [[COERCE75]], align 16 // CHECK-NEXT: [[COERCE75_TUPLE:%.*]] = load { , }, ptr [[COERCE75]], align 16 // CHECK-NEXT: [[COERCE75_EXTRACT0:%.*]] = extractvalue { , } [[COERCE75_TUPLE]], 0 @@ -1125,7 +1125,7 @@ void f(__clang_svmfloat8x4_t, __clang_svmfloat8x4_t); // COMPAT_17-NEXT: [[COERCE74_EXTRACT2:%.*]] = extractvalue { , , , } [[COERCE74_TUPLE]], 2 // COMPAT_17-NEXT: [[COERCE74_EXTRACT3:%.*]] = extractvalue { , , , } [[COERCE74_TUPLE]], 3 // COMPAT_17-NEXT: store { , , , } zeroinitializer, ptr [[BYVAL_TEMP]], align 2 -// COMPAT_17-NEXT: call void @_Z1f10svboolx4_t10svboolx4_t( [[COERCE74_EXTRACT0]], [[COERCE74_EXTRACT1]], [[COERCE74_EXTRACT2]], [[COERCE74_EXTRACT3]], ptr noundef [[BYVAL_TEMP]]) +// COMPAT_17-NEXT: call void @_Z1f10svboolx4_t10svboolx4_t( [[COERCE74_EXTRACT0]], [[COERCE74_EXTRACT1]], [[COERCE74_EXTRACT2]], [[COERCE74_EXTRACT3]], ptr dead_on_return noundef [[BYVAL_TEMP]]) // COMPAT_17-NEXT: store { , } zeroinitializer, ptr [[COERCE75]], align 16 // COMPAT_17-NEXT: [[COERCE75_TUPLE:%.*]] = load { , }, ptr [[COERCE75]], align 16 // COMPAT_17-NEXT: [[COERCE75_EXTRACT0:%.*]] = extractvalue { , } [[COERCE75_TUPLE]], 0 diff --git a/clang/test/CodeGenCXX/arm-cc.cpp b/clang/test/CodeGenCXX/arm-cc.cpp index 68e1b7e4e1e46..939615fcc69e0 100644 --- a/clang/test/CodeGenCXX/arm-cc.cpp +++ b/clang/test/CodeGenCXX/arm-cc.cpp @@ -17,4 +17,4 @@ void baz() { } // CHECK: declare void @_Z3fooPv(ptr dead_on_unwind writable sret(%class.SMLoc) align 4, ptr noundef) -// CHECK: declare void @_Z3zed5SMLoc(ptr noundef) +// CHECK: declare void @_Z3zed5SMLoc(ptr dead_on_return noundef) diff --git a/clang/test/CodeGenCXX/attr-target-mv-inalloca.cpp b/clang/test/CodeGenCXX/attr-target-mv-inalloca.cpp index c341bd2b855ff..f2d602b3b523e 100644 --- a/clang/test/CodeGenCXX/attr-target-mv-inalloca.cpp +++ b/clang/test/CodeGenCXX/attr-target-mv-inalloca.cpp @@ -55,18 +55,18 @@ void usage() { // WINDOWS-NEXT: ret i32 %[[RET]] -// WINDOWS64: define dso_local noundef i32 @"?bar@@YAHUFoo@@@Z"(ptr noundef %[[O:[0-9a-zA-Z]+]]) +// WINDOWS64: define dso_local noundef i32 @"?bar@@YAHUFoo@@@Z"(ptr dead_on_return noundef %[[O:[0-9a-zA-Z]+]]) // WINDOWS64: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds nuw %struct.Foo, ptr %[[O]], i32 0, i32 0 // WINDOWS64: %[[LOAD:[0-9a-zA-Z]+]] = load i32, ptr %[[X]] // WINDOWS64: ret i32 %[[LOAD]] -// WINDOWS64: define dso_local noundef i32 @"?bar@@YAHUFoo@@@Z.sse4.2"(ptr noundef %[[O:[0-9a-zA-Z]+]]) +// WINDOWS64: define dso_local noundef i32 @"?bar@@YAHUFoo@@@Z.sse4.2"(ptr dead_on_return noundef %[[O:[0-9a-zA-Z]+]]) // WINDOWS64: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds nuw %struct.Foo, ptr %[[O]], i32 0, i32 0 // WINDOWS64: %[[LOAD:[0-9a-zA-Z]+]] = load i32, ptr %[[X]] // WINDOWS64: %[[ADD:[0-9a-zA-Z]+]] = add nsw i32 %[[LOAD]], 1 // WINDOWS64: ret i32 %[[ADD]] -// WINDOWS64: define dso_local noundef i32 @"?bar@@YAHUFoo@@@Z.arch_ivybridge"(ptr noundef %[[O:[0-9a-zA-Z]+]]) +// WINDOWS64: define dso_local noundef i32 @"?bar@@YAHUFoo@@@Z.arch_ivybridge"(ptr dead_on_return noundef %[[O:[0-9a-zA-Z]+]]) // WINDOWS64: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds nuw %struct.Foo, ptr %[[O]], i32 0, i32 0 // WINDOWS64: %[[LOAD:[0-9a-zA-Z]+]] = load i32, ptr %[[X]] // WINDOWS64: %[[ADD:[0-9a-zA-Z]+]] = add nsw i32 %[[LOAD]], 2 @@ -75,7 +75,7 @@ void usage() { // WINDOWS64: define dso_local void @"?usage@@YAXXZ"() // WINDOWS64: %[[F:[0-9a-zA-Z]+]] = alloca %struct.Foo // WINDOWS64: %[[ARG:[0-9a-zA-Z.]+]] = alloca %struct.Foo -// WINDOWS64: %[[CALL:[0-9a-zA-Z]+]] = call noundef i32 @"?bar@@YAHUFoo@@@Z.resolver"(ptr noundef %[[ARG]]) +// WINDOWS64: %[[CALL:[0-9a-zA-Z]+]] = call noundef i32 @"?bar@@YAHUFoo@@@Z.resolver"(ptr dead_on_return noundef %[[ARG]]) // WINDOWS64: define weak_odr dso_local i32 @"?bar@@YAHUFoo@@@Z.resolver"(ptr %0) // WINDOWS64: %[[RET:[0-9a-zA-Z]+]] = musttail call i32 @"?bar@@YAHUFoo@@@Z.arch_ivybridge"(ptr %0) diff --git a/clang/test/CodeGenCXX/copy-initialization.cpp b/clang/test/CodeGenCXX/copy-initialization.cpp index aa0c6395f158d..4e6194cc040c2 100644 --- a/clang/test/CodeGenCXX/copy-initialization.cpp +++ b/clang/test/CodeGenCXX/copy-initialization.cpp @@ -12,7 +12,7 @@ struct Bar { void f(Foo); -// CHECK-LABEL: define{{.*}} void @_Z1g3Foo(ptr noundef %foo) +// CHECK-LABEL: define{{.*}} void @_Z1g3Foo(ptr dead_on_return noundef %foo) void g(Foo foo) { // CHECK: call void @_ZN3BarC1Ev // CHECK: @_ZNK3BarcvRK3FooEv diff --git a/clang/test/CodeGenCXX/debug-info.cpp b/clang/test/CodeGenCXX/debug-info.cpp index 8594a897ef7c0..9cf26ba83ba3e 100644 --- a/clang/test/CodeGenCXX/debug-info.cpp +++ b/clang/test/CodeGenCXX/debug-info.cpp @@ -4,7 +4,7 @@ // CHECK: @_ZN6pr96081xE ={{.*}} global ptr null, align 8, !dbg [[X:![0-9]+]] // CHECK: define{{.*}} void @_ZN7pr147634funcENS_3fooE -// CHECK-SAME: ptr noundef [[param:%.*]]) +// CHECK-SAME: ptr dead_on_return noundef [[param:%.*]]) // CHECK-NEXT: entry: // CHECK-NEXT: alloca ptr, align 8 // CHECK-NEXT: [[param_addr_storage:%.*]] = alloca ptr, align 8 diff --git a/clang/test/CodeGenCXX/empty-nontrivially-copyable.cpp b/clang/test/CodeGenCXX/empty-nontrivially-copyable.cpp index c7d3a017414ef..c8f5a0f7c2ea6 100644 --- a/clang/test/CodeGenCXX/empty-nontrivially-copyable.cpp +++ b/clang/test/CodeGenCXX/empty-nontrivially-copyable.cpp @@ -13,7 +13,7 @@ struct Empty { }; bool foo(Empty e) { -// CHECK: @_Z3foo5Empty(ptr noundef %e) +// CHECK: @_Z3foo5Empty(ptr dead_on_return noundef %e) // CHECK: call {{.*}} @_ZN5Empty5checkEv(ptr {{[^,]*}} %e) return e.check(); } @@ -21,6 +21,6 @@ bool foo(Empty e) { void caller(Empty &e) { // CHECK: @_Z6callerR5Empty(ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %e) // CHECK: call {{.*}} @_ZN5EmptyC1ERKS_(ptr {{[^,]*}} [[NEWTMP:%.*]], ptr -// CHECK: call {{.*}} @_Z3foo5Empty(ptr noundef [[NEWTMP]]) +// CHECK: call {{.*}} @_Z3foo5Empty(ptr dead_on_return noundef [[NEWTMP]]) foo(e); } diff --git a/clang/test/CodeGenCXX/fastcall.cpp b/clang/test/CodeGenCXX/fastcall.cpp index 4c94c1623ee16..405917f7a14bb 100644 --- a/clang/test/CodeGenCXX/fastcall.cpp +++ b/clang/test/CodeGenCXX/fastcall.cpp @@ -15,6 +15,6 @@ struct S1 { void __attribute__((fastcall)) foo2(S1 a, int b); void bar2(S1 a, int b) { // CHECK-LABEL: define{{.*}} void @_Z4bar22S1i - // CHECK: call x86_fastcallcc void @_Z4foo22S1i(ptr inreg %{{.*}}, i32 inreg % + // CHECK: call x86_fastcallcc void @_Z4foo22S1i(ptr dead_on_return inreg %{{.*}}, i32 inreg % foo2(a, b); } diff --git a/clang/test/CodeGenCXX/homogeneous-aggregates.cpp b/clang/test/CodeGenCXX/homogeneous-aggregates.cpp index 63ffc6b5bfac8..5ebeb8aad4c18 100644 --- a/clang/test/CodeGenCXX/homogeneous-aggregates.cpp +++ b/clang/test/CodeGenCXX/homogeneous-aggregates.cpp @@ -41,8 +41,8 @@ struct D5 : I1, I2, I3 {}; // homogeneous aggregate // PPC: define{{.*}} void @_Z7func_D12D1(ptr dead_on_unwind noalias writable sret(%struct.D1) align 8 %agg.result, [3 x i64] %x.coerce) // ARM32: define{{.*}} arm_aapcs_vfpcc void @_Z7func_D12D1(ptr dead_on_unwind noalias writable sret(%struct.D1) align 8 %agg.result, [3 x i64] %x.coerce) -// ARM64: define{{.*}} void @_Z7func_D12D1(ptr dead_on_unwind noalias writable sret(%struct.D1) align 8 %agg.result, ptr noundef %x) -// X64: define dso_local x86_vectorcallcc void @"\01_Z7func_D12D1@@24"(ptr dead_on_unwind noalias writable sret(%struct.D1) align 8 %agg.result, ptr noundef %x) +// ARM64: define{{.*}} void @_Z7func_D12D1(ptr dead_on_unwind noalias writable sret(%struct.D1) align 8 %agg.result, ptr dead_on_return noundef %x) +// X64: define dso_local x86_vectorcallcc void @"\01_Z7func_D12D1@@24"(ptr dead_on_unwind noalias writable sret(%struct.D1) align 8 %agg.result, ptr dead_on_return noundef %x) D1 CC func_D1(D1 x) { return x; } // PPC: define{{.*}} [3 x double] @_Z7func_D22D2([3 x double] %x.coerce) @@ -53,7 +53,7 @@ D2 CC func_D2(D2 x) { return x; } // PPC: define{{.*}} void @_Z7func_D32D3(ptr dead_on_unwind noalias writable sret(%struct.D3) align 8 %agg.result, [4 x i64] %x.coerce) // ARM32: define{{.*}} arm_aapcs_vfpcc void @_Z7func_D32D3(ptr dead_on_unwind noalias writable sret(%struct.D3) align 8 %agg.result, [4 x i64] %x.coerce) -// ARM64: define{{.*}} void @_Z7func_D32D3(ptr dead_on_unwind noalias writable sret(%struct.D3) align 8 %agg.result, ptr noundef %x) +// ARM64: define{{.*}} void @_Z7func_D32D3(ptr dead_on_unwind noalias writable sret(%struct.D3) align 8 %agg.result, ptr dead_on_return noundef %x) D3 CC func_D3(D3 x) { return x; } // PPC: define{{.*}} [4 x double] @_Z7func_D42D4([4 x double] %x.coerce) @@ -201,7 +201,7 @@ struct NonHFA { virtual void f1(); }; double foo(NonHFA v) { return v.x + v.y; } -// WOA64: define dso_local noundef double @"?foo@polymorphic@@YANUNonHFA@1@@Z"(ptr noundef %{{.*}}) +// WOA64: define dso_local noundef double @"?foo@polymorphic@@YANUNonHFA@1@@Z"(ptr dead_on_return noundef %{{.*}}) } namespace trivial_copy_assignment { struct HFA { @@ -221,7 +221,7 @@ struct NonHFA { NonHFA &operator=(const NonHFA&); }; double foo(NonHFA v) { return v.x + v.y; } -// WOA64: define dso_local noundef double @"?foo@non_trivial_copy_assignment@@YANUNonHFA@1@@Z"(ptr noundef %{{.*}}) +// WOA64: define dso_local noundef double @"?foo@non_trivial_copy_assignment@@YANUNonHFA@1@@Z"(ptr dead_on_return noundef %{{.*}}) } namespace user_provided_ctor { struct HFA { @@ -251,7 +251,7 @@ struct NonHFA { ~NonHFA(); }; double foo(NonHFA v) { return v.x + v.y; } -// WOA64: define dso_local noundef double @"?foo@non_trivial_dtor@@YANUNonHFA@1@@Z"(ptr noundef %{{.*}}) +// WOA64: define dso_local noundef double @"?foo@non_trivial_dtor@@YANUNonHFA@1@@Z"(ptr dead_on_return noundef %{{.*}}) } namespace non_empty_base { struct non_empty_base { double d; }; @@ -272,7 +272,7 @@ struct NonHFA { empty e; }; double foo(NonHFA v) { return v.x + v.y; } -// WOA64: define dso_local noundef double @"?foo@empty_field@@YANUNonHFA@1@@Z"(ptr noundef %{{.*}}) +// WOA64: define dso_local noundef double @"?foo@empty_field@@YANUNonHFA@1@@Z"(ptr dead_on_return noundef %{{.*}}) } namespace non_empty_field { struct non_empty { double d; }; diff --git a/clang/test/CodeGenCXX/inalloca-lambda.cpp b/clang/test/CodeGenCXX/inalloca-lambda.cpp index dc78aa2773f89..0d527e1a02e5f 100644 --- a/clang/test/CodeGenCXX/inalloca-lambda.cpp +++ b/clang/test/CodeGenCXX/inalloca-lambda.cpp @@ -22,7 +22,7 @@ void test() { // CHECK: %[[V:.*]] = getelementptr inbounds nuw <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0 // CHECK: %call = call x86_thiscallcc noundef i32 // CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z" -// CHECK-SAME: (ptr noundef %this, ptr noundef %[[V]]) +// CHECK-SAME: (ptr noundef %this, ptr dead_on_return noundef %[[V]]) // CHECK: define internal noundef i32 // CHECK-SAME: @"?__invoke@@?0??test@@YAXXZ@CA?A?@@UA@@@Z" @@ -31,12 +31,12 @@ void test() { // CHECK: %[[VAR:.*]] = getelementptr inbounds nuw <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0 // CHECK: %call = call x86_thiscallcc noundef i32 // CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z" -// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]]) +// CHECK-SAME: (ptr noundef %unused.capture, ptr dead_on_return noundef %[[VAR]]) // CHECK: ret i32 %call // CHECK: define internal x86_thiscallcc noundef i32 // CHECK-SAME: @"?__impl@@?0??test@@YAXXZ@QBE?A?@@UA@@@Z" -// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]]) +// CHECK-SAME: (ptr noundef %this, ptr dead_on_return noundef %[[ARG:.*]]) // CHECK: %this.addr = alloca ptr, align 4 // CHECK: store ptr %this, ptr %this.addr, align 4 // CHECK: %this1 = load ptr, ptr %this.addr, align 4 diff --git a/clang/test/CodeGenCXX/inalloca-overaligned.cpp b/clang/test/CodeGenCXX/inalloca-overaligned.cpp index 3751751ec0bca..305b8c5dccd10 100644 --- a/clang/test/CodeGenCXX/inalloca-overaligned.cpp +++ b/clang/test/CodeGenCXX/inalloca-overaligned.cpp @@ -57,7 +57,7 @@ int receive_both(Both o) { } // CHECK-LABEL: define dso_local noundef i32 @"?receive_both@@Y{{.*}}" -// CHECK-SAME: (ptr noundef %o) +// CHECK-SAME: (ptr dead_on_return noundef %o) int pass_both() { gvi32 = receive_both(Both()); @@ -67,7 +67,7 @@ int pass_both() { // CHECK-LABEL: define dso_local noundef i32 @"?pass_both@@Y{{.*}}" // CHECK: [[TMP:%[^ ]*]] = alloca %struct.Both, align 8 // CHECK: call x86_thiscallcc noundef ptr @"??0Both@@QAE@XZ"(ptr {{[^,]*}} [[TMP]]) -// CHECK: call noundef i32 @"?receive_both@@Y{{.*}}"(ptr noundef [[TMP]]) +// CHECK: call noundef i32 @"?receive_both@@Y{{.*}}"(ptr dead_on_return noundef [[TMP]]) int receive_inalloca_both(NonTrivial nt, Both o) { return nt.x + o.x + o.y; @@ -101,11 +101,11 @@ struct [[trivial_abi]] alignas(8) MyPtr { int receiveMyPtr(MyPtr o) { return *o.ptr; } // CHECK-LABEL: define dso_local noundef i32 @"?receiveMyPtr@@Y{{.*}}" -// CHECK-SAME: (ptr noundef %o) +// CHECK-SAME: (ptr dead_on_return noundef %o) int passMyPtr() { return receiveMyPtr(MyPtr()); } // CHECK-LABEL: define dso_local noundef i32 @"?passMyPtr@@Y{{.*}}" // CHECK: [[TMP:%[^ ]*]] = alloca %struct.MyPtr, align 8 // CHECK: call x86_thiscallcc noundef ptr @"??0MyPtr@@QAE@XZ"(ptr {{[^,]*}} [[TMP]]) -// CHECK: call noundef i32 @"?receiveMyPtr@@Y{{.*}}"(ptr noundef [[TMP]]) +// CHECK: call noundef i32 @"?receiveMyPtr@@Y{{.*}}"(ptr dead_on_return noundef [[TMP]]) diff --git a/clang/test/CodeGenCXX/inalloca-vector.cpp b/clang/test/CodeGenCXX/inalloca-vector.cpp index d1bacb4f0dc8c..2db4c49df116a 100644 --- a/clang/test/CodeGenCXX/inalloca-vector.cpp +++ b/clang/test/CodeGenCXX/inalloca-vector.cpp @@ -56,7 +56,7 @@ void __fastcall fastcall_receive_vec(__m128 x, __m128 y, __m128 z, __m128 w, int // CHECK-SAME: (<4 x float> inreg noundef %x, // CHECK-SAME: <4 x float> inreg noundef %y, // CHECK-SAME: <4 x float> inreg noundef %z, -// CHECK-SAME: ptr inreg noundef %0, +// CHECK-SAME: ptr dead_on_return inreg noundef %0, // CHECK-SAME: i32 inreg noundef %edx, // CHECK-SAME: ptr inalloca(<{ ptr, %struct.NonTrivial }>) %1) @@ -73,6 +73,6 @@ void __vectorcall vectorcall_receive_vec(double xmm0, double xmm1, double xmm2, // CHECK-SAME: <4 x float> inreg noundef %x, // CHECK-SAME: <4 x float> inreg noundef %y, // CHECK-SAME: <4 x float> inreg noundef %z, -// CHECK-SAME: ptr inreg noundef %0, +// CHECK-SAME: ptr dead_on_return inreg noundef %0, // CHECK-SAME: i32 inreg noundef %edx, // CHECK-SAME: ptr inalloca(<{ ptr, %struct.NonTrivial }>) %1) diff --git a/clang/test/CodeGenCXX/inheriting-constructor.cpp b/clang/test/CodeGenCXX/inheriting-constructor.cpp index 100ca269d7f3c..21751bea055dc 100644 --- a/clang/test/CodeGenCXX/inheriting-constructor.cpp +++ b/clang/test/CodeGenCXX/inheriting-constructor.cpp @@ -166,7 +166,7 @@ namespace inalloca_nonvirt { // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"(ptr {{[^,]*}} %[[ARG3]], i32 3) // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"(ptr {{[^,]*}} %[[ARG1]], i32 1) // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"( - // WIN64: call {{.*}} @"??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(ptr{{.*}}, ptr %[[ARG1]], i32 2, ptr %[[ARG3]], ptr{{.*}} %[[TMP]]) + // WIN64: call {{.*}} @"??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(ptr{{.*}}, ptr dead_on_return %[[ARG1]], i32 2, ptr dead_on_return %[[ARG3]], ptr{{.*}} %[[TMP]]) // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"( // WIN64: call void @"??1Q@@QEAA@XZ"(ptr {{[^,]*}} %[[TMP]]) @@ -202,7 +202,7 @@ namespace inalloca_nonvirt { // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"(ptr {{[^,]*}} %[[ARG3]], i32 3) // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"(ptr {{[^,]*}} %[[ARG1]], i32 1) // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"( - // WIN64: call {{.*}} @"??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(ptr{{.*}}, ptr %[[ARG1]], i32 2, ptr %[[ARG3]], ptr{{.*}} %[[TMP]]) + // WIN64: call {{.*}} @"??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(ptr{{.*}}, ptr dead_on_return %[[ARG1]], i32 2, ptr dead_on_return %[[ARG3]], ptr{{.*}} %[[TMP]]) // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"( // WIN64: call void @"??1Q@@QEAA@XZ"(ptr {{[^,]*}} %[[TMP]]) } @@ -253,7 +253,7 @@ namespace inalloca_virt { // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"(ptr {{[^,]*}} %[[ARG3]], i32 3) // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"(ptr {{[^,]*}} %[[ARG1]], i32 1) // WIN64: br i1 - // WIN64: call {{.*}} @"??0A@inalloca_virt@@QEAA@UQ@@H0$$QEAU2@@Z"(ptr{{.*}}, ptr %[[ARG1]], i32 2, ptr %[[ARG3]], ptr{{.*}} %[[TMP]]) + // WIN64: call {{.*}} @"??0A@inalloca_virt@@QEAA@UQ@@H0$$QEAU2@@Z"(ptr{{.*}}, ptr dead_on_return %[[ARG1]], i32 2, ptr dead_on_return %[[ARG3]], ptr{{.*}} %[[TMP]]) // WIN64: br // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"( // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"( @@ -302,7 +302,7 @@ namespace inalloca_virt { // WIN64: call {{.*}} @"??0Q@@QEAA@H@Z"(ptr {{[^,]*}} %[[ARG1]], i32 1) // WIN64: br i1 // WIN64: store {{.*}} @"??_8C@inalloca_virt@@7B@" - // WIN64: call {{.*}} @"??0A@inalloca_virt@@QEAA@UQ@@H0$$QEAU2@@Z"(ptr{{.*}}, ptr %[[ARG1]], i32 2, ptr %[[ARG3]], ptr{{.*}} %[[TMP]]) + // WIN64: call {{.*}} @"??0A@inalloca_virt@@QEAA@UQ@@H0$$QEAU2@@Z"(ptr{{.*}}, ptr dead_on_return %[[ARG1]], i32 2, ptr dead_on_return %[[ARG3]], ptr{{.*}} %[[TMP]]) // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"( // WIN64: call {{.*}} @"??0Z@@QEAA@XZ"( // WIN64: call void @"??1Q@@QEAA@XZ"(ptr {{[^,]*}} %[[TMP]]) diff --git a/clang/test/CodeGenCXX/member-function-pointer-calls.cpp b/clang/test/CodeGenCXX/member-function-pointer-calls.cpp index ff511c0243801..f06cda8b7684e 100644 --- a/clang/test/CodeGenCXX/member-function-pointer-calls.cpp +++ b/clang/test/CodeGenCXX/member-function-pointer-calls.cpp @@ -16,7 +16,7 @@ int f(A* a, int (A::*fp)()) { // CHECK-NOT: } // CHECK: ret i32 1 // MINGW64-LABEL: define dso_local noundef i32 @_Z2g1v() -// MINGW64: call noundef i32 @_Z1fP1AMS_FivE(ptr noundef %{{.*}}, ptr noundef %{{.*}}) +// MINGW64: call noundef i32 @_Z1fP1AMS_FivE(ptr noundef %{{.*}}, ptr dead_on_return noundef %{{.*}}) int g1() { A a; return f(&a, &A::vf1); @@ -26,7 +26,7 @@ int g1() { // CHECK-NOT: } // CHECK: ret i32 2 // MINGW64-LABEL: define dso_local noundef i32 @_Z2g2v() -// MINGW64: call noundef i32 @_Z1fP1AMS_FivE(ptr noundef %{{.*}}, ptr noundef %{{.*}}) +// MINGW64: call noundef i32 @_Z1fP1AMS_FivE(ptr noundef %{{.*}}, ptr dead_on_return noundef %{{.*}}) int g2() { A a; return f(&a, &A::vf2); diff --git a/clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp b/clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp index b551df747c073..63a4d5525336b 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp @@ -24,7 +24,7 @@ void foo(A a, A b, A c) { // X86: ret void // X64-LABEL: define dso_local void @"?foo@@YAXUA@@00@Z" -// X64: (ptr noundef %[[a:[^,]*]], ptr noundef %[[b:[^,]*]], ptr noundef %[[c:[^)]*]]) +// X64: (ptr dead_on_return noundef %[[a:[^,]*]], ptr dead_on_return noundef %[[b:[^,]*]], ptr dead_on_return noundef %[[c:[^)]*]]) // X64: call void @"??1A@@QEAA@XZ"(ptr {{[^,]*}} %[[a]]) // X64: call void @"??1A@@QEAA@XZ"(ptr {{[^,]*}} %[[b]]) // X64: call void @"??1A@@QEAA@XZ"(ptr {{[^,]*}} %[[c]]) @@ -64,7 +64,7 @@ void call_foo() { // X64: invoke noundef ptr @"??0A@@QEAA@H@Z"(ptr {{[^,]*}} %[[arg2:[^,]*]], i32 noundef 2) // X64: invoke noundef ptr @"??0A@@QEAA@H@Z"(ptr {{[^,]*}} %[[arg1:[^,]*]], i32 noundef 1) // X64: call void @"?foo@@YAXUA@@00@Z" -// X64: (ptr noundef %[[arg1]], ptr noundef %[[arg2]], ptr noundef %[[arg3]]) +// X64: (ptr dead_on_return noundef %[[arg1]], ptr dead_on_return noundef %[[arg2]], ptr dead_on_return noundef %[[arg3]]) // X64: ret void // // lpad2: diff --git a/clang/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp b/clang/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp index 5654db3ba8151..813abb03a7810 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp @@ -22,10 +22,10 @@ C::C() {} // force emission // CHECK32-NEXT: ret void // CHECK64-LABEL: define linkonce_odr dso_local void @"?foo@C@byval_thunk@@W7EAAXUAgg@2@@Z" -// CHECK64: (ptr noundef %this, ptr noundef %x) +// CHECK64: (ptr noundef %this, ptr dead_on_return noundef %x) // CHECK64: getelementptr i8, ptr %{{.*}}, i32 -8 // CHECK64: call void @"?foo@C@byval_thunk@@UEAAXUAgg@2@@Z" -// CHECK64: (ptr {{[^,]*}} %{{.*}}, ptr noundef %x) +// CHECK64: (ptr {{[^,]*}} %{{.*}}, ptr dead_on_return noundef %x) // CHECK64-NOT: call // CHECK64: ret void } @@ -54,10 +54,10 @@ C::C() {} // force emission // CHECK32-NEXT: ret void // CHECK64-LABEL: define linkonce_odr dso_local void @"?foo@C@stdcall_thunk@@W7EAAXUAgg@2@@Z" -// CHECK64: (ptr noundef %this, ptr noundef %x) +// CHECK64: (ptr noundef %this, ptr dead_on_return noundef %x) // CHECK64: getelementptr i8, ptr %{{.*}}, i32 -8 // CHECK64: call void @"?foo@C@stdcall_thunk@@UEAAXUAgg@2@@Z" -// CHECK64: (ptr {{[^,]*}} %{{.*}}, ptr noundef %x) +// CHECK64: (ptr {{[^,]*}} %{{.*}}, ptr dead_on_return noundef %x) // CHECK64-NOT: call // CHECK64: ret void } @@ -86,10 +86,10 @@ C::C() {} // force emission // CHECK32-NEXT: ret ptr %[[rv]] // CHECK64-LABEL: define linkonce_odr dso_local void @"?foo@C@sret_thunk@@W7EAA?AUAgg@2@U32@@Z" -// CHECK64: (ptr noundef %this, ptr dead_on_unwind noalias writable sret(%"struct.sret_thunk::Agg") align 4 %agg.result, ptr noundef %x) +// CHECK64: (ptr noundef %this, ptr dead_on_unwind noalias writable sret(%"struct.sret_thunk::Agg") align 4 %agg.result, ptr dead_on_return noundef %x) // CHECK64: getelementptr i8, ptr %{{.*}}, i32 -8 // CHECK64: call void @"?foo@C@sret_thunk@@UEAA?AUAgg@2@U32@@Z" -// CHECK64: (ptr {{[^,]*}} %{{.*}}, ptr dead_on_unwind writable sret(%"struct.sret_thunk::Agg") align 4 %agg.result, ptr noundef %x) +// CHECK64: (ptr {{[^,]*}} %{{.*}}, ptr dead_on_unwind writable sret(%"struct.sret_thunk::Agg") align 4 %agg.result, ptr dead_on_return noundef %x) // CHECK64-NOT: call // CHECK64: ret void } diff --git a/clang/test/CodeGenCXX/microsoft-abi-eh-async.cpp b/clang/test/CodeGenCXX/microsoft-abi-eh-async.cpp new file mode 100644 index 0000000000000..b83173742a2a7 --- /dev/null +++ b/clang/test/CodeGenCXX/microsoft-abi-eh-async.cpp @@ -0,0 +1,209 @@ +// REQUIRES: x86-registered-target + +// RUN: %clang_cl -c --target=x86_64-windows-msvc /EHa -O2 /GS- \ +// RUN: -Xclang=-import-call-optimization \ +// RUN: /clang:-S /clang:-o- -- %s 2>&1 \ +// RUN: | FileCheck %s + +#ifdef __clang__ +#define NO_TAIL __attribute((disable_tail_calls)) +#else +#define NO_TAIL +#endif + +void might_throw(); +void other_func(int x); + +void does_not_throw() noexcept(true); + +extern "C" void __declspec(dllimport) some_dll_import(); + +class HasDtor { + int x; + char foo[40]; + +public: + explicit HasDtor(int x); + ~HasDtor(); +}; + +class BadError { +public: + int errorCode; +}; + +void normal_has_regions() { + // CHECK-LABEL: .def "?normal_has_regions@@YAXXZ" + // CHECK: .seh_endprologue + + // <-- state -1 (none) + { + HasDtor hd{42}; + + // <-- state goes from -1 to 0 + // because state changes, we expect the HasDtor::HasDtor() call to have a NOP + // CHECK: call "??0HasDtor@@QEAA@H@Z" + // CHECK-NEXT: nop + + might_throw(); + // CHECK: call "?might_throw@@YAXXZ" + // CHECK-NEXT: nop + + // <-- state goes from 0 to -1 because we're about to call HasDtor::~HasDtor() + // CHECK: call "??1HasDtor@@QEAA@XZ" + // <-- state -1 + } + + // <-- state -1 + other_func(10); + // CHECK: call "?other_func@@YAXH@Z" + // CHECK-NEXT: nop + // CHECK: .seh_startepilogue + + // <-- state -1 +} + +// This tests a tail call to a destructor. +void case_dtor_arg_empty_body(HasDtor x) +{ + // CHECK-LABEL: .def "?case_dtor_arg_empty_body@@YAXVHasDtor@@@Z" + // CHECK: jmp "??1HasDtor@@QEAA@XZ" +} + +int case_dtor_arg_empty_with_ret(HasDtor x) +{ + // CHECK-LABEL: .def "?case_dtor_arg_empty_with_ret@@YAHVHasDtor@@@Z" + // CHECK: .seh_endprologue + + // CHECK: call "??1HasDtor@@QEAA@XZ" + // CHECK-NOT: nop + + // The call to HasDtor::~HasDtor() should NOT have a NOP because the + // following "mov eax, 100" instruction is in the same EH state. + + return 100; + + // CHECK: mov eax, 100 + // CHECK: .seh_startepilogue + // CHECK: .seh_endepilogue + // CHECK: .seh_endproc +} + +int case_noexcept_dtor(HasDtor x) noexcept(true) +{ + // CHECK: .def "?case_noexcept_dtor@@YAHVHasDtor@@@Z" + // CHECK: call "??1HasDtor@@QEAA@XZ" + // CHECK-NEXT: mov eax, 100 + // CHECK: .seh_startepilogue + return 100; +} + +void case_except_simple_call() NO_TAIL +{ + does_not_throw(); +} +// CHECK-LABEL: .def "?case_except_simple_call@@YAXXZ" +// CHECK: .seh_endprologue +// CHECK-NEXT: call "?does_not_throw@@YAXXZ" +// CHECK-NEXT: nop +// CHECK-NEXT: .seh_startepilogue +// CHECK: .seh_endproc + +void case_noexcept_simple_call() noexcept(true) NO_TAIL +{ + does_not_throw(); +} +// CHECK-LABEL: .def "?case_noexcept_simple_call@@YAXXZ" +// CHECK: .seh_endprologue +// CHECK-NEXT: call "?does_not_throw@@YAXXZ" +// CHECK-NEXT: nop +// CHECK-NEXT: .seh_startepilogue +// CHECK: .seh_endepilogue +// CHECK-NEXT: ret +// CHECK-NEXT: .seh_endproc + +// This tests that the destructor is called right before SEH_BeginEpilogue, +// but in a function that has a return value. Loading the return value +// counts as a real instruction, so there is no need for a NOP after the +// dtor call. +int case_dtor_arg_calls_no_throw(HasDtor x) +{ + does_not_throw(); // no NOP expected + return 100; +} +// CHECK-LABEL: .def "?case_dtor_arg_calls_no_throw@@YAHVHasDtor@@@Z" +// CHECK: .seh_endprologue +// CHECK: "?does_not_throw@@YAXXZ" +// CHECK-NEXT: nop +// CHECK: "??1HasDtor@@QEAA@XZ" +// CHECK-NEXT: mov eax, 100 +// CHECK: .seh_startepilogue +// CHECK: .seh_endproc + +// Check the behavior of CALLs that are at the end of MBBs. If a CALL is within +// a non-null EH state (state -1) and is at the end of an MBB, then we expect +// to find an EH_LABEL after the CALL. This causes us to insert a NOP, which +// is the desired result. +void case_dtor_runs_after_join(int x) { + // CHECK-LABEL: .def "?case_dtor_runs_after_join@@YAXH@Z" + // CHECK: .seh_endprologue + + // <-- EH state -1 + + // ctor call does not need a NOP, because it has real instructions after it + HasDtor hd{42}; + // CHECK: call "??0HasDtor@@QEAA@H@Z" + // CHECK-NEXT: nop + // CHECK: test + + // <-- EH state transition from -1 0 + if (x) { + might_throw(); // <-- NOP expected (at end of BB w/ EH_LABEL) + // CHECK: call "?might_throw@@YAXXZ" + // CHECK-NEXT: nop + } else { + other_func(10); // <-- NOP expected (at end of BB w/ EH_LABEL) + // CHECK: call "?other_func@@YAXH@Z" + // CHECK-NEXT: nop + } + does_not_throw(); + // <-- EH state transition 0 to -1 + // ~HasDtor() runs + + // CHECK: .seh_endproc + + // CHECK: "$ip2state$?case_dtor_runs_after_join@@YAXH@Z": + // CHECK-NEXT: .long [[func_begin:.Lfunc_begin([0-9]+)@IMGREL]] + // CHECK-NEXT: .long -1 + // CHECK-NEXT: .long [[tmp1:.Ltmp([0-9]+)]]@IMGREL + // CHECK-NEXT: .long 0 + // CHECK-NEXT: .long [[tmp2:.Ltmp([0-9]+)]]@IMGREL + // CHECK-NEXT: .long -1 +} + + +// Check the behavior of NOP padding around tail calls. +// We do not expect to insert NOPs around tail calls. +// However, the first call (to other_func()) does get a NOP +// because it comes before .seh_startepilogue. +void case_tail_call_no_eh(bool b) { + // tail call; no NOP padding after JMP + if (b) { + does_not_throw(); + // <-- no NOP here + return; + } + + other_func(20); + // <-- NOP does get inserted here +} +// CHECK-LABEL: .def "?case_tail_call_no_eh@@YAX_N@Z" +// CHECK: test +// CHECK-NEXT: je .LBB +// CHECK: jmp "?does_not_throw@@YAXXZ" +// CHECK-SAME: TAILCALL +// CHECK-NEXT: .LBB +// CHECK-NEXT: mov ecx, 20 +// CHECK-NEXT: jmp "?other_func@@YAXH@Z" +// CHECK-SAME: TAILCALL +// CHECK-NEXT: # -- End function diff --git a/clang/test/CodeGenCXX/microsoft-abi-eh-disabled.cpp b/clang/test/CodeGenCXX/microsoft-abi-eh-disabled.cpp new file mode 100644 index 0000000000000..4c6493f15dee5 --- /dev/null +++ b/clang/test/CodeGenCXX/microsoft-abi-eh-disabled.cpp @@ -0,0 +1,139 @@ +// RUN: %clang_cl -c --target=x86_64-windows-msvc -EHs-c- -O2 -GS- \ +// RUN: -Xclang=-import-call-optimization \ +// RUN: -clang:-S -clang:-o- -- %s 2>&1 \ +// RUN: | FileCheck %s + +#ifdef __clang__ +#define NO_TAIL __attribute((disable_tail_calls)) +#else +#define NO_TAIL +#endif + +void might_throw(); +void other_func(int x); + +void does_not_throw() noexcept(true); + +extern "C" void __declspec(dllimport) some_dll_import(); + +class HasDtor { + int x; + char foo[40]; + +public: + explicit HasDtor(int x); + ~HasDtor(); +}; + +void normal_has_regions() { + { + HasDtor hd{42}; + + // because state changes, we expect the HasDtor::HasDtor() call to have a NOP + might_throw(); + } + + other_func(10); +} +// CHECK-LABEL: .def "?normal_has_regions@@YAXXZ" +// CHECK: .seh_endprologue +// CHECK: call "??0HasDtor@@QEAA@H@Z" +// CHECK-NEXT: call "?might_throw@@YAXXZ" +// CHECK-NEXT: mov +// CHECK: call "??1HasDtor@@QEAA@XZ" +// CHECK-NEXT: mov ecx, 10 +// CHECK-NEXT: call "?other_func@@YAXH@Z" +// CHECK-NEXT: nop +// CHECK-NEXT: .seh_startepilogue +// CHECK-NOT: "$ip2state$?normal_has_regions@@YAXXZ" + +// This tests a tail call to a destructor. +void case_dtor_arg_empty_body(HasDtor x) +{ +} +// CHECK-LABEL: .def "?case_dtor_arg_empty_body@@YAXVHasDtor@@@Z" +// CHECK: jmp "??1HasDtor@@QEAA@XZ" + +int case_dtor_arg_empty_with_ret(HasDtor x) +{ + // The call to HasDtor::~HasDtor() should NOT have a NOP because the + // following "mov eax, 100" instruction is in the same EH state. + return 100; +} +// CHECK-LABEL: .def "?case_dtor_arg_empty_with_ret@@YAHVHasDtor@@@Z" +// CHECK: .seh_endprologue +// CHECK: call "??1HasDtor@@QEAA@XZ" +// CHECK-NOT: nop +// CHECK: mov eax, 100 +// CHECK: .seh_startepilogue +// CHECK: .seh_endepilogue +// CHECK: .seh_endproc + +void case_except_simple_call() NO_TAIL +{ + does_not_throw(); +} + +// This tests that the destructor is called right before SEH_BeginEpilogue, +// but in a function that has a return value. +int case_dtor_arg_calls_no_throw(HasDtor x) +{ + does_not_throw(); // no NOP expected + return 100; +} + +// Check the behavior of CALLs that are at the end of MBBs. If a CALL is within +// a non-null EH state (state -1) and is at the end of an MBB, then we expect +// to find an EH_LABEL after the CALL. This causes us to insert a NOP, which +// is the desired result. +void case_dtor_runs_after_join(int x) { + + // ctor call does not need a NOP, because it has real instructions after it + HasDtor hd{42}; + + if (x) { + might_throw(); + } else { + other_func(10); + } + does_not_throw(); + // ~HasDtor() runs +} + +// CHECK-LABEL: .def "?case_dtor_runs_after_join@@YAXH@Z" +// CHECK: .seh_endprologue +// CHECK: call "??0HasDtor@@QEAA@H@Z" +// CHECK-NEXT: test +// CHECK: call "?might_throw@@YAXXZ" +// CHECK-NEXT: jmp +// CHECK: call "?other_func@@YAXH@Z" +// CHECK-NEXT: .LBB +// CHECK: call "?does_not_throw@@YAXXZ" +// CHECK-NEXT: lea +// CHECK-NEXT: call "??1HasDtor@@QEAA@XZ" +// CHECK-NEXT: nop +// CHECK-NEXT: .seh_startepilogue +// CHECK-NOT: "$ip2state$?case_dtor_runs_after_join@@YAXH@Z": + + +// Check the behavior of NOP padding around tail calls. +// We do not expect to insert NOPs around tail calls. +// However, the first call (to other_func()) does get a NOP +// because it comes before .seh_startepilogue. +void case_tail_call_no_eh() { + // ordinary call + other_func(10); + + // tail call; no NOP padding after JMP + does_not_throw(); +} + +// CHECK-LABEL: .def "?case_tail_call_no_eh@@YAXXZ" +// CHECK: .seh_endprologue +// CHECK: call "?other_func@@YAXH@Z" +// CHECK-NEXT: nop +// CHECK-NEXT: .seh_startepilogue +// CHECK: .seh_endepilogue +// CHECK: jmp "?does_not_throw@@YAXXZ" +// CHECK-NOT: nop +// CHECK: .seh_endproc diff --git a/clang/test/CodeGenCXX/microsoft-abi-eh-ip2state.cpp b/clang/test/CodeGenCXX/microsoft-abi-eh-ip2state.cpp new file mode 100644 index 0000000000000..d6b9b58e55845 --- /dev/null +++ b/clang/test/CodeGenCXX/microsoft-abi-eh-ip2state.cpp @@ -0,0 +1,241 @@ +// RUN: %clang_cl -c --target=x86_64-windows-msvc -O2 -EHsc -GS- \ +// RUN: -Xclang=-import-call-optimization \ +// RUN: -clang:-S -clang:-o- -- %s 2>&1 \ +// RUN: | FileCheck %s + +#ifdef __clang__ +#define NO_TAIL __attribute((disable_tail_calls)) +#else +#define NO_TAIL +#endif + +void might_throw(); +void other_func(int x); + +void does_not_throw() noexcept(true); + +extern "C" void __declspec(dllimport) some_dll_import(); + +class HasDtor { + int x; + char foo[40]; + +public: + explicit HasDtor(int x); + ~HasDtor(); +}; + +class BadError { +public: + int errorCode; +}; + +// Verify that when NOP padding for IP2State is active *and* Import Call +// Optimization is active that we see both forms of NOP padding. +void case_calls_dll_import() NO_TAIL { + some_dll_import(); +} +// CHECK-LABEL: .def "?case_calls_dll_import@@YAXXZ" +// CHECK: .seh_endprologue +// CHECK: .Limpcall{{[0-9]+}}: +// CHECK-NEXT: rex64 +// CHECK-NEXT: call __imp_some_dll_import +// CHECK-NEXT: nop dword ptr {{\[.*\]}} +// CHECK-NEXT: nop +// CHECK-NEXT: .seh_startepilogue + +void normal_has_regions() { + + // <-- state -1 (none) + { + HasDtor hd{42}; + + // <-- state goes from -1 to 0 + // because state changes, we expect the HasDtor::HasDtor() call to have a NOP + + might_throw(); + + // <-- state goes from 0 to -1 because we're about to call HasDtor::~HasDtor() + // <-- state -1 + } + + // <-- state -1 + other_func(10); + + // <-- state -1 +} +// CHECK-LABEL: .def "?normal_has_regions@@YAXXZ" +// CHECK: .seh_endprologue +// CHECK: call "??0HasDtor@@QEAA@H@Z" +// CHECK-NEXT: nop +// CHECK: call "?might_throw@@YAXXZ" +// CHECK-NEXT: nop +// CHECK: call "??1HasDtor@@QEAA@XZ" +// CHECK: call "?other_func@@YAXH@Z" +// CHECK-NEXT: nop +// CHECK: .seh_startepilogue + +// This tests a tail call to a destructor. +void case_dtor_arg_empty_body(HasDtor x) +{ +} +// CHECK-LABEL: .def "?case_dtor_arg_empty_body@@YAXVHasDtor@@@Z" +// CHECK: jmp "??1HasDtor@@QEAA@XZ" + +int case_dtor_arg_empty_with_ret(HasDtor x) +{ + // CHECK-LABEL: .def "?case_dtor_arg_empty_with_ret@@YAHVHasDtor@@@Z" + // CHECK: .seh_endprologue + + // CHECK: call "??1HasDtor@@QEAA@XZ" + // CHECK-NOT: nop + + // The call to HasDtor::~HasDtor() should NOT have a NOP because the + // following "mov eax, 100" instruction is in the same EH state. + + return 100; + + // CHECK: mov eax, 100 + // CHECK: .seh_startepilogue + // CHECK: .seh_endepilogue + // CHECK: .seh_endproc +} + +int case_noexcept_dtor(HasDtor x) noexcept(true) +{ + // CHECK: .def "?case_noexcept_dtor@@YAHVHasDtor@@@Z" + // CHECK: call "??1HasDtor@@QEAA@XZ" + // CHECK-NEXT: mov eax, 100 + // CHECK-NEXT: .seh_startepilogue + return 100; +} + +// Simple call of a function that can throw +void case_except_simple_call() NO_TAIL +{ + might_throw(); +} +// CHECK-LABEL: .def "?case_except_simple_call@@YAXXZ" +// CHECK: .seh_endprologue +// CHECK-NEXT: call "?might_throw@@YAXXZ" +// CHECK-NEXT: nop +// CHECK-NEXT: .seh_startepilogue + +// Simple call of a function that cannot throw, in a noexcept context. +void case_noexcept_simple_call() noexcept(true) NO_TAIL +{ + does_not_throw(); +} +// CHECK-LABEL: .def "?case_noexcept_simple_call@@YAXXZ" +// CHECK: .seh_endprologue +// CHECK-NEXT: call "?does_not_throw@@YAXXZ" +// CHECK-NEXT: nop +// CHECK-NEXT: .seh_startepilogue + + +// This tests that the destructor is called right before SEH_BeginEpilogue, +// but in a function that has a return value. +int case_dtor_arg_calls_no_throw(HasDtor x) +{ + does_not_throw(); // no NOP expected + return 100; +} + +// Check the behavior of CALLs that are at the end of MBBs. If a CALL is within +// a non-null EH state (state -1) and is at the end of an MBB, then we expect +// to find an EH_LABEL after the CALL. This causes us to insert a NOP, which +// is the desired result. +void case_dtor_runs_after_join(int x) { + // CHECK-LABEL: .def "?case_dtor_runs_after_join@@YAXH@Z" + // CHECK: .seh_endprologue + + // <-- EH state -1 + + // ctor call does not need a NOP, because it has real instructions after it + HasDtor hd{42}; + // CHECK: call "??0HasDtor@@QEAA@H@Z" + // CHECK-NEXT: test + + // <-- EH state transition from -1 0 + if (x) { + might_throw(); // <-- NOP expected (at end of BB w/ EH_LABEL) + // CHECK: call "?might_throw@@YAXXZ" + // CHECK-NEXT: nop + } else { + other_func(10); // <-- NOP expected (at end of BB w/ EH_LABEL) + // CHECK: call "?other_func@@YAXH@Z" + // CHECK-NEXT: nop + } + does_not_throw(); + // <-- EH state transition 0 to -1 + // ~HasDtor() runs + + // CHECK: .seh_endproc + + // CHECK: "$ip2state$?case_dtor_runs_after_join@@YAXH@Z": + // CHECK-NEXT: .long [[func_begin:.Lfunc_begin([0-9]+)@IMGREL]] + // CHECK-NEXT: .long -1 + // CHECK-NEXT: .long [[tmp1:.Ltmp([0-9]+)]]@IMGREL + // CHECK-NEXT: .long 0 + // CHECK-NEXT: .long [[tmp2:.Ltmp([0-9]+)]]@IMGREL + // CHECK-NEXT: .long -1 +} + + +// Check the behavior of NOP padding around tail calls. +// We do not expect to insert NOPs around tail calls. +// However, the first call (to other_func()) does get a NOP +// because it comes before .seh_startepilogue. +void case_tail_call_no_eh() { + // CHECK-LABEL: .def "?case_tail_call_no_eh@@YAXXZ" + // CHECK: .seh_endprologue + + // ordinary call + other_func(10); + // CHECK: call "?other_func@@YAXH@Z" + // CHECK-NEXT: nop + + // tail call; no NOP padding after JMP + does_not_throw(); + + // CHECK: .seh_startepilogue + // CHECK: .seh_endepilogue + // CHECK: jmp "?does_not_throw@@YAXXZ" + // CHECK-NOT: nop + // CHECK: .seh_endproc +} + + +// Check the behavior of a try/catch +int case_try_catch() { + // CHECK-LABEL: .def "?case_try_catch@@YAHXZ" + // CHECK: .seh_endprologue + + // Because of the EH_LABELs, the ctor and other_func() get NOPs. + + int result = 0; + try { + // CHECK: call "??0HasDtor@@QEAA@H@Z" + // CHECK-NEXT: nop + HasDtor hd{20}; + + // CHECK: call "?other_func@@YAXH@Z" + // CHECK-NEXT: nop + other_func(10); + + // CHECK: call "??1HasDtor@@QEAA@XZ" + // CHECK: mov + } catch (BadError& e) { + result = 1; + } + return result; + + // CHECK: .seh_endproc + + // CHECK: .def "?dtor$4@?0??case_try_catch@@YAHXZ@4HA" + // CHECK: .seh_endprologue + // CHECK: call "??1HasDtor@@QEAA@XZ" + // CHECK-NEXT: nop + // CHECK: .seh_startepilogue + // CHECK: .seh_endproc +} diff --git a/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp index 806bc5b63ef02..8defb68c668b2 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp @@ -428,7 +428,7 @@ bool nullTestDataUnspecified(int Unspecified::*mp) { // Pass this large type indirectly. // X64-LABEL: define dso_local noundef zeroext i1 @"?nullTestDataUnspecified@@ -// X64: (ptr noundef %0) +// X64: (ptr dead_on_return noundef %0) } bool nullTestFunctionUnspecified(void (Unspecified::*mp)()) { @@ -590,7 +590,7 @@ bool unspecFuncMemptrEq(void (Unspecified::*l)(), void (Unspecified::*r)()) { // CHECK: } // X64-LABEL: define dso_local noundef zeroext i1 @"?unspecFuncMemptrEq@@ -// X64: (ptr noundef %0, ptr noundef %1) +// X64: (ptr dead_on_return noundef %0, ptr dead_on_return noundef %1) } bool unspecFuncMemptrNeq(void (Unspecified::*l)(), void (Unspecified::*r)()) { @@ -635,7 +635,7 @@ bool unspecDataMemptrEq(int Unspecified::*l, int Unspecified::*r) { // CHECK: } // X64-LABEL: define dso_local noundef zeroext i1 @"?unspecDataMemptrEq@@ -// X64: (ptr noundef %0, ptr noundef %1) +// X64: (ptr dead_on_return noundef %0, ptr dead_on_return noundef %1) } void (Multiple::*convertB2FuncToMultiple(void (B2::*mp)()))() { diff --git a/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp b/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp index 6e8ba3953b2cf..767bf168633ae 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp @@ -175,7 +175,7 @@ void multibyte_arg(Multibyte s) {} void packed_arg(Packed s) {} // LINUX-LABEL: define{{.*}} void @_Z10packed_arg6Packed(ptr noundef byval(%struct.Packed) align 4 %s) // WIN32: define dso_local void @"?packed_arg@@YAXUPacked@@@Z"(ptr noundef byval(%struct.Packed) align 4 %s) -// WIN64: define dso_local void @"?packed_arg@@YAXUPacked@@@Z"(ptr noundef %s) +// WIN64: define dso_local void @"?packed_arg@@YAXUPacked@@@Z"(ptr dead_on_return noundef %s) // Test that dtors are invoked in the callee. void small_arg_with_dtor(SmallWithDtor s) {} @@ -190,7 +190,7 @@ void small_arg_with_dtor(SmallWithDtor s) {} // WOA64: } // FIXME: MSVC incompatible! -// WOA: define dso_local arm_aapcs_vfpcc void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(ptr noundef %s) {{.*}} { +// WOA: define dso_local arm_aapcs_vfpcc void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(ptr dead_on_return noundef %s) {{.*}} { // WOA: call arm_aapcs_vfpcc void @"??1SmallWithDtor@@QAA@XZ"(ptr {{[^,]*}} %s) // WOA: } @@ -220,7 +220,7 @@ void ref_small_arg_with_dtor(const SmallWithDtor &s) { } // WIN64-LABEL: define dso_local void @"?ref_small_arg_with_dtor@@YAXAEBUSmallWithDtor@@@Z"(ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %s) void big_arg_with_dtor(BigWithDtor s) {} -// WIN64-LABEL: define dso_local void @"?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(ptr noundef %s) +// WIN64-LABEL: define dso_local void @"?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(ptr dead_on_return noundef %s) // WIN64: call void @"??1BigWithDtor@@QEAA@XZ" // WIN64: } @@ -231,7 +231,7 @@ void call_big_arg_with_dtor() { // larger than 8 bytes and is passed indirectly. // WIN64-LABEL: define dso_local void @"?call_big_arg_with_dtor@@YAXXZ"() // WIN64: call noundef ptr @"??0BigWithDtor@@QEAA@XZ" -// WIN64: call void @"?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(ptr noundef %{{.*}}) +// WIN64: call void @"?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(ptr dead_on_return noundef %{{.*}}) // WIN64-NOT: call void @"??1BigWithDtor@@QEAA@XZ" // WIN64: ret void @@ -259,22 +259,22 @@ void eh_cleanup_arg_with_dtor() { // WIN32: } void small_arg_with_vftable(SmallWithVftable s) {} -// LINUX-LABEL: define{{.*}} void @_Z22small_arg_with_vftable16SmallWithVftable(ptr noundef %s) +// LINUX-LABEL: define{{.*}} void @_Z22small_arg_with_vftable16SmallWithVftable(ptr dead_on_return noundef %s) // WIN32: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(ptr inalloca(<{ %struct.SmallWithVftable }>) %0) -// WIN64: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(ptr noundef %s) -// WOA64: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(ptr noundef %s) +// WIN64: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(ptr dead_on_return noundef %s) +// WOA64: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(ptr dead_on_return noundef %s) void medium_arg_with_copy_ctor(MediumWithCopyCtor s) {} -// LINUX-LABEL: define{{.*}} void @_Z25medium_arg_with_copy_ctor18MediumWithCopyCtor(ptr noundef %s) +// LINUX-LABEL: define{{.*}} void @_Z25medium_arg_with_copy_ctor18MediumWithCopyCtor(ptr dead_on_return noundef %s) // WIN32: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(ptr inalloca(<{ %struct.MediumWithCopyCtor }>) %0) -// WIN64: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(ptr noundef %s) -// WOA: define dso_local arm_aapcs_vfpcc void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(ptr noundef %s) -// WOA64: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(ptr noundef %s) +// WIN64: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(ptr dead_on_return noundef %s) +// WOA: define dso_local arm_aapcs_vfpcc void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(ptr dead_on_return noundef %s) +// WOA64: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(ptr dead_on_return noundef %s) void big_arg(Big s) {} // LINUX-LABEL: define{{.*}} void @_Z7big_arg3Big(ptr noundef byval(%struct.Big) align 4 %s) // WIN32: define dso_local void @"?big_arg@@YAXUBig@@@Z"(ptr noundef byval(%struct.Big) align 4 %s) -// WIN64: define dso_local void @"?big_arg@@YAXUBig@@@Z"(ptr noundef %s) +// WIN64: define dso_local void @"?big_arg@@YAXUBig@@@Z"(ptr dead_on_return noundef %s) // PR27607: We would attempt to load i32 value out of the reference instead of // just loading the pointer from the struct during argument expansion. @@ -346,7 +346,7 @@ class Class { void thiscall_method_arg(Big s) {} // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE3Big(ptr {{[^,]*}} %this, ptr noundef byval(%struct.Big) align 4 %s) // WIN32: define {{.*}} void @"?thiscall_method_arg@Class@@QAEXUBig@@@Z"(ptr {{[^,]*}} %this, ptr noundef byval(%struct.Big) align 4 %s) - // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg@Class@@QEAAXUBig@@@Z"(ptr {{[^,]*}} %this, ptr noundef %s) + // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg@Class@@QEAAXUBig@@@Z"(ptr {{[^,]*}} %this, ptr dead_on_return noundef %s) }; void use_class() { diff --git a/clang/test/CodeGenCXX/microsoft-abi-unknown-arch.cpp b/clang/test/CodeGenCXX/microsoft-abi-unknown-arch.cpp index 9e37e71e257fd..b7653632cf882 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-unknown-arch.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-unknown-arch.cpp @@ -18,4 +18,4 @@ A B::foo(A x) { return x; } -// CHECK-LABEL: define{{.*}} void @"?foo@B@@QEAA?AUA@@U2@@Z"(ptr {{[^,]*}} %this, ptr dead_on_unwind noalias writable sret(%struct.A) align 4 %agg.result, ptr noundef %x) +// CHECK-LABEL: define{{.*}} void @"?foo@B@@QEAA?AUA@@U2@@Z"(ptr {{[^,]*}} %this, ptr dead_on_unwind noalias writable sret(%struct.A) align 4 %agg.result, ptr dead_on_return noundef %x) diff --git a/clang/test/CodeGenCXX/ms-property.cpp b/clang/test/CodeGenCXX/ms-property.cpp index 744de224b2f9a..d9fbf46dacb25 100644 --- a/clang/test/CodeGenCXX/ms-property.cpp +++ b/clang/test/CodeGenCXX/ms-property.cpp @@ -105,7 +105,7 @@ int main(int argc, char **argv) { // CHECK: [[ARGC:%.+]] = load i32, ptr % // CHECK: [[P1_X_ARGC_0:%.+]] = call noundef i32 @"?GetX@S@@QEAAHHH@Z"(ptr {{[^,]*}} [[P1]], i32 noundef [[ARGC]], i32 noundef 0) // CHECK: [[CAST:%.+]] = trunc i32 [[P1_X_ARGC_0]] to i8 - // CHECK: [[P2_Y_p1_X_ARGC_0_T:%.+]] = call noundef i8 @"?GetY@?$St@M@@QEAADDVTest1@@@Z"(ptr {{[^,]*}} [[P2_2]], i8 noundef [[CAST]], ptr noundef %{{.+}}) + // CHECK: [[P2_Y_p1_X_ARGC_0_T:%.+]] = call noundef i8 @"?GetY@?$St@M@@QEAADDVTest1@@@Z"(ptr {{[^,]*}} [[P2_2]], i8 noundef [[CAST]], ptr dead_on_return noundef %{{.+}}) // CHECK: [[CAST:%.+]] = sitofp i8 [[P2_Y_p1_X_ARGC_0_T]] to float // CHECK: [[J:%.+]] = load i32, ptr % // CHECK: [[CAST1:%.+]] = sitofp i32 [[J]] to float @@ -124,6 +124,6 @@ int main(int argc, char **argv) { // CHECK: call noundef i32 @"?GetX@?$St@H@@QEAAHHH@Z"(ptr {{[^,]*}} [[BAR]], i32 noundef %{{.+}} i32 noundef %{{.+}}) // CHECK: call void @"?PutY@?$St@H@@QEAAXDHN@Z"(ptr {{[^,]*}} [[BAR]], i8 noundef %{{.+}}, i32 noundef %{{.+}}, double noundef %{{.+}} // CHECK: call noundef i32 @"?GetX@?$St@H@@QEAAHHH@Z"(ptr {{[^,]*}} [[BAR]], i32 noundef %{{.+}} i32 noundef %{{.+}}) -// CHECK: call noundef i8 @"?GetY@?$St@H@@QEAADDVTest1@@@Z"(ptr {{[^,]*}} [[BAR]], i8 noundef %{{.+}}, ptr noundef %{{.+}}) +// CHECK: call noundef i8 @"?GetY@?$St@H@@QEAADDVTest1@@@Z"(ptr {{[^,]*}} [[BAR]], i8 noundef %{{.+}}, ptr dead_on_return noundef %{{.+}}) // CHECK: call noundef i32 @"?PutX@?$St@H@@QEAAHHHH@Z"(ptr {{[^,]*}} [[BAR]], i32 noundef %{{.+}}, i32 noundef %{{.+}}, i32 noundef %{{.+}}) #endif //HEADER diff --git a/clang/test/CodeGenCXX/nrvo.cpp b/clang/test/CodeGenCXX/nrvo.cpp index 1141bc35de582..5b0fc914120e3 100644 --- a/clang/test/CodeGenCXX/nrvo.cpp +++ b/clang/test/CodeGenCXX/nrvo.cpp @@ -2197,7 +2197,7 @@ void test16() { // http://wg21.link/p2025r2#ex-9 // CHECK-EH-11-NEXT: br i1 [[CMP9]], label [[IF_THEN10:%.*]], label [[IF_END11:%.*]] // CHECK-EH-11: if.then10: // CHECK-EH-11-NEXT: store i32 3, ptr [[CLEANUP_DEST_SLOT]], align 4 -// CHECK-EH-11-NEXT: br label [[CLEANUP]], !llvm.loop [[LOOP3:![0-9]+]] +// CHECK-EH-11-NEXT: br label [[CLEANUP]], !llvm.loop [[LOOP4:![0-9]+]] // CHECK-EH-11: if.end11: // CHECK-EH-11-NEXT: [[TMP4:%.*]] = load i32, ptr [[I_ADDR]], align 4 // CHECK-EH-11-NEXT: [[CMP12:%.*]] = icmp eq i32 [[TMP4]], 3 @@ -2239,7 +2239,7 @@ void test16() { // http://wg21.link/p2025r2#ex-9 // CHECK-EH-11-NEXT: i32 2, label [[IMPOSSIBLE]] // CHECK-EH-11-NEXT: ] // CHECK-EH-11: cleanup.cont: -// CHECK-EH-11-NEXT: br label [[WHILE_BODY]], !llvm.loop [[LOOP3]] +// CHECK-EH-11-NEXT: br label [[WHILE_BODY]], !llvm.loop [[LOOP4]] // CHECK-EH-11: while.end: // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) // CHECK-EH-11-NEXT: br label [[RETURN]] diff --git a/clang/test/CodeGenCXX/pass-by-value-noalias.cpp b/clang/test/CodeGenCXX/pass-by-value-noalias.cpp index 773cf6b81c3b2..947379d9b8b92 100644 --- a/clang/test/CodeGenCXX/pass-by-value-noalias.cpp +++ b/clang/test/CodeGenCXX/pass-by-value-noalias.cpp @@ -14,8 +14,8 @@ struct Foo { // Make sure noalias is added to indirect arguments with trivially copyable types // if -fpass-by-value-is-noalias is provided. -// WITH_NOALIAS: define{{.*}} void @_Z4take3Foo(ptr noalias noundef %arg) -// NO_NOALIAS: define{{.*}} void @_Z4take3Foo(ptr noundef %arg) +// WITH_NOALIAS: define{{.*}} void @_Z4take3Foo(ptr dead_on_return noalias noundef %arg) +// NO_NOALIAS: define{{.*}} void @_Z4take3Foo(ptr dead_on_return noundef %arg) void take(Foo arg) {} int G; @@ -38,8 +38,8 @@ struct NonTrivial { // Make sure noalias is not added to indirect arguments that are not trivially // copyable even if -fpass-by-value-is-noalias is provided. -// WITH_NOALIAS: define{{.*}} void @_Z4take10NonTrivial(ptr noundef %arg) -// NO_NOALIAS: define{{.*}} void @_Z4take10NonTrivial(ptr noundef %arg) +// WITH_NOALIAS: define{{.*}} void @_Z4take10NonTrivial(ptr dead_on_return noundef %arg) +// NO_NOALIAS: define{{.*}} void @_Z4take10NonTrivial(ptr dead_on_return noundef %arg) void take(NonTrivial arg) {} // Escape examples. Pointers to the objects passed to take() may escape, depending on whether a temporary copy is created or not (e.g. due to NRVO). @@ -54,8 +54,8 @@ struct A { }; A *p; -// WITH_NOALIAS: define{{.*}} void @_Z4take1A(ptr noalias noundef %arg) -// NO_NOALIAS: define{{.*}} void @_Z4take1A(ptr noundef %arg) +// WITH_NOALIAS: define{{.*}} void @_Z4take1A(ptr dead_on_return noalias noundef %arg) +// NO_NOALIAS: define{{.*}} void @_Z4take1A(ptr dead_on_return noundef %arg) void take(A arg) {} // WITH_NOALIAS: define{{.*}} void @_Z7CreateAPP1A(ptr dead_on_unwind noalias writable sret(%struct.A) align 1 %agg.result, ptr noundef %where) diff --git a/clang/test/CodeGenCXX/pragma-loop.cpp b/clang/test/CodeGenCXX/pragma-loop.cpp index 4857299f1c037..8cb3346247daf 100644 --- a/clang/test/CodeGenCXX/pragma-loop.cpp +++ b/clang/test/CodeGenCXX/pragma-loop.cpp @@ -203,6 +203,43 @@ void for_test_scalable_1(int *List, int Length) { } } +// Verify for loop is not performing vectorization +void for_test_width_1(int *List, int Length) { +#pragma clang loop vectorize_width(1) interleave_count(4) unroll(disable) distribute(disable) + for (int i = 0; i < Length; i++) { + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_20:.*]] + List[i] = i * 2; + } +} + +// Verify for loop is not performing vectorization +void for_test_fixed_1(int *List, int Length) { +#pragma clang loop vectorize_width(1, fixed) interleave_count(4) unroll(disable) distribute(disable) + for (int i = 0; i < Length; i++) { + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_21:.*]] + List[i] = i * 2; + } +} + + +// Verify unroll attributes are directly attached to the loop metadata +void for_test_vectorize_disable_unroll(int *List, int Length) { +#pragma clang loop vectorize(disable) unroll_count(8) + for (int i = 0; i < Length; i++) { + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_22:.*]] + List[i] = i * 2; + } +} + +// Verify unroll attributes are directly attached to the loop metadata +void for_test_interleave_vectorize_disable_unroll(int *List, int Length) { +#pragma clang loop vectorize(disable) interleave_count(4) unroll_count(8) + for (int i = 0; i < Length; i++) { + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_23:.*]] + List[i] = i * 2; + } +} + // CHECK-DAG: ![[MP:[0-9]+]] = !{!"llvm.loop.mustprogress"} // CHECK-DAG: ![[UNROLL_DISABLE:[0-9]+]] = !{!"llvm.loop.unroll.disable"} @@ -270,3 +307,7 @@ void for_test_scalable_1(int *List, int Length) { // CHECK-DAG: ![[LOOP_17]] = distinct !{![[LOOP_17]], ![[MP]], ![[UNROLL_DISABLE]], ![[DISTRIBUTE_DISABLE]], ![[FIXED_VEC]], ![[INTERLEAVE_4]], ![[VECTORIZE_ENABLE]]} // CHECK-DAG: ![[LOOP_18]] = distinct !{![[LOOP_18]], ![[MP]], ![[UNROLL_DISABLE]], ![[DISTRIBUTE_DISABLE]], ![[SCALABLE_VEC]], ![[INTERLEAVE_4]], ![[VECTORIZE_ENABLE]]} // CHECK-DAG: ![[LOOP_19]] = distinct !{![[LOOP_19]], ![[MP]], ![[UNROLL_DISABLE]], ![[DISTRIBUTE_DISABLE]], ![[WIDTH_1]], ![[SCALABLE_VEC]], ![[INTERLEAVE_4]], ![[VECTORIZE_ENABLE]]} +// CHECK-DAG: ![[LOOP_20]] = distinct !{![[LOOP_20]], ![[MP]], ![[UNROLL_DISABLE]], ![[DISTRIBUTE_DISABLE]], ![[WIDTH_1]], ![[FIXED_VEC]], ![[INTERLEAVE_4]]} +// CHECK-DAG: ![[LOOP_21]] = distinct !{![[LOOP_21]], ![[MP]], ![[UNROLL_DISABLE]], ![[DISTRIBUTE_DISABLE]], ![[WIDTH_1]], ![[FIXED_VEC]], ![[INTERLEAVE_4]]} +// CHECK-DAG: ![[LOOP_22]] = distinct !{![[LOOP_22]], ![[MP]], ![[WIDTH_1]], ![[ISVECTORIZED]], ![[UNROLL_8]]} +// CHECK-DAG: ![[LOOP_23]] = distinct !{![[LOOP_23]], ![[MP]], ![[WIDTH_1]], ![[INTERLEAVE_4]], ![[ISVECTORIZED]], ![[UNROLL_8]]} diff --git a/clang/test/CodeGenCXX/ptrauth-qualifier-struct.cpp b/clang/test/CodeGenCXX/ptrauth-qualifier-struct.cpp index daeea77774ec8..0310535362e3d 100644 --- a/clang/test/CodeGenCXX/ptrauth-qualifier-struct.cpp +++ b/clang/test/CodeGenCXX/ptrauth-qualifier-struct.cpp @@ -24,7 +24,7 @@ struct __attribute__((trivial_abi)) TrivialSA { // Check that TrivialSA is passed indirectly despite being annotated with // 'trivial_abi'. -// CHECK: define {{.*}}void @_Z18testParamTrivialSA9TrivialSA(ptr noundef %{{.*}}) +// CHECK: define {{.*}}void @_Z18testParamTrivialSA9TrivialSA(ptr dead_on_return noundef %{{.*}}) void testParamTrivialSA(TrivialSA a) { } diff --git a/clang/test/CodeGenCXX/regparm.cpp b/clang/test/CodeGenCXX/regparm.cpp index b9735485db8de..a31394016fb55 100644 --- a/clang/test/CodeGenCXX/regparm.cpp +++ b/clang/test/CodeGenCXX/regparm.cpp @@ -11,7 +11,7 @@ struct S1 { }; void __attribute__((regparm(3))) foo2(S1 a, int b); -// CHECK: declare void @_Z4foo22S1i(ptr inreg noundef, i32 inreg noundef) +// CHECK: declare void @_Z4foo22S1i(ptr dead_on_return inreg noundef, i32 inreg noundef) void bar2(S1 a, int b) { foo2(a, b); } diff --git a/clang/test/CodeGenCXX/trivial_abi.cpp b/clang/test/CodeGenCXX/trivial_abi.cpp index b8cc0d1cc6528..eacbde594e517 100644 --- a/clang/test/CodeGenCXX/trivial_abi.cpp +++ b/clang/test/CodeGenCXX/trivial_abi.cpp @@ -140,7 +140,7 @@ void testIgnoredSmall() { testReturnSmall(); } -// CHECK: define{{.*}} void @_Z14testParamLarge5Large(ptr noundef %[[A:.*]]) +// CHECK: define{{.*}} void @_Z14testParamLarge5Large(ptr dead_on_return noundef %[[A:.*]]) // CHECK: %[[CALL:.*]] = call noundef ptr @_ZN5LargeD1Ev(ptr {{[^,]*}} %[[A]]) // CHECK: ret void // CHECK: } @@ -163,7 +163,7 @@ Large testReturnLarge() { // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE]], align 8 // CHECK: %[[CALL:.*]] = call noundef ptr @_ZN5LargeC1Ev(ptr {{[^,]*}} %[[T]]) // CHECK: %[[CALL1:.*]] = call noundef ptr @_ZN5LargeC1ERKS_(ptr {{[^,]*}} %[[AGG_TMP]], ptr noundef nonnull align 8 dereferenceable(520) %[[T]]) -// CHECK: call void @_Z14testParamLarge5Large(ptr noundef %[[AGG_TMP]]) +// CHECK: call void @_Z14testParamLarge5Large(ptr dead_on_return noundef %[[AGG_TMP]]) // CHECK: %[[CALL2:.*]] = call noundef ptr @_ZN5LargeD1Ev(ptr {{[^,]*}} %[[T]]) // CHECK: ret void // CHECK: } @@ -176,7 +176,7 @@ void testCallLarge0() { // CHECK: define{{.*}} void @_Z14testCallLarge1v() // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8 // CHECK: call void @_Z15testReturnLargev(ptr dead_on_unwind writable sret(%[[STRUCT_LARGE]]) align 8 %[[AGG_TMP]]) -// CHECK: call void @_Z14testParamLarge5Large(ptr noundef %[[AGG_TMP]]) +// CHECK: call void @_Z14testParamLarge5Large(ptr dead_on_return noundef %[[AGG_TMP]]) // CHECK: ret void // CHECK: } @@ -244,7 +244,7 @@ void testExceptionSmall() { // CHECK: call noundef ptr @_ZN5LargeC1Ev(ptr {{[^,]*}} %[[AGG_TMP]]) // CHECK: invoke noundef ptr @_ZN5LargeC1Ev(ptr {{[^,]*}} %[[AGG_TMP1]]) -// CHECK: call void @_Z20calleeExceptionLarge5LargeS_(ptr noundef %[[AGG_TMP]], ptr noundef %[[AGG_TMP1]]) +// CHECK: call void @_Z20calleeExceptionLarge5LargeS_(ptr dead_on_return noundef %[[AGG_TMP]], ptr dead_on_return noundef %[[AGG_TMP1]]) // CHECK-NEXT: ret void // CHECK: landingpad { ptr, i32 } diff --git a/clang/test/CodeGenCXX/uncopyable-args.cpp b/clang/test/CodeGenCXX/uncopyable-args.cpp index 31192b65cc362..2d09732f9d3c2 100644 --- a/clang/test/CodeGenCXX/uncopyable-args.cpp +++ b/clang/test/CodeGenCXX/uncopyable-args.cpp @@ -59,12 +59,12 @@ void bar() { // CHECK-LABEL: define{{.*}} void @_ZN9move_ctor3barEv() // CHECK: call void @_Z{{.*}}C1Ev( // CHECK-NOT: call -// NEWABI: call void @_ZN9move_ctor3fooENS_1AE(ptr noundef %{{.*}}) +// NEWABI: call void @_ZN9move_ctor3fooENS_1AE(ptr dead_on_return noundef %{{.*}}) // OLDABI: call void @_ZN9move_ctor3fooENS_1AE(ptr %{{.*}}) -// NEWABI-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(ptr noundef) +// NEWABI-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(ptr dead_on_return noundef) // OLDABI-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(ptr) -// WIN64-LABEL: declare dso_local void @"?foo@move_ctor@@YAXUA@1@@Z"(ptr noundef) +// WIN64-LABEL: declare dso_local void @"?foo@move_ctor@@YAXUA@1@@Z"(ptr dead_on_return noundef) } namespace all_deleted { @@ -81,12 +81,12 @@ void bar() { // CHECK-LABEL: define{{.*}} void @_ZN11all_deleted3barEv() // CHECK: call void @_Z{{.*}}C1Ev( // CHECK-NOT: call -// NEWABI: call void @_ZN11all_deleted3fooENS_1AE(ptr noundef %{{.*}}) +// NEWABI: call void @_ZN11all_deleted3fooENS_1AE(ptr dead_on_return noundef %{{.*}}) // OLDABI: call void @_ZN11all_deleted3fooENS_1AE(ptr %{{.*}}) -// NEWABI-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(ptr noundef) +// NEWABI-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(ptr dead_on_return noundef) // OLDABI-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(ptr) -// WIN64-LABEL: declare dso_local void @"?foo@all_deleted@@YAXUA@1@@Z"(ptr noundef) +// WIN64-LABEL: declare dso_local void @"?foo@all_deleted@@YAXUA@1@@Z"(ptr dead_on_return noundef) } namespace implicitly_deleted { @@ -102,14 +102,14 @@ void bar() { // CHECK-LABEL: define{{.*}} void @_ZN18implicitly_deleted3barEv() // CHECK: call void @_Z{{.*}}C1Ev( // CHECK-NOT: call -// NEWABI: call void @_ZN18implicitly_deleted3fooENS_1AE(ptr noundef %{{.*}}) +// NEWABI: call void @_ZN18implicitly_deleted3fooENS_1AE(ptr dead_on_return noundef %{{.*}}) // OLDABI: call void @_ZN18implicitly_deleted3fooENS_1AE(ptr %{{.*}}) -// NEWABI-LABEL: declare void @_ZN18implicitly_deleted3fooENS_1AE(ptr noundef) +// NEWABI-LABEL: declare void @_ZN18implicitly_deleted3fooENS_1AE(ptr dead_on_return noundef) // OLDABI-LABEL: declare void @_ZN18implicitly_deleted3fooENS_1AE(ptr) // In MSVC 2013, the copy ctor is not deleted by a move assignment. In MSVC 2015, it is. // WIN64-18-LABEL: declare dso_local void @"?foo@implicitly_deleted@@YAXUA@1@@Z"(i64 -// WIN64-19-LABEL: declare dso_local void @"?foo@implicitly_deleted@@YAXUA@1@@Z"(ptr noundef) +// WIN64-19-LABEL: declare dso_local void @"?foo@implicitly_deleted@@YAXUA@1@@Z"(ptr dead_on_return noundef) } namespace one_deleted { @@ -125,12 +125,12 @@ void bar() { // CHECK-LABEL: define{{.*}} void @_ZN11one_deleted3barEv() // CHECK: call void @_Z{{.*}}C1Ev( // CHECK-NOT: call -// NEWABI: call void @_ZN11one_deleted3fooENS_1AE(ptr noundef %{{.*}}) +// NEWABI: call void @_ZN11one_deleted3fooENS_1AE(ptr dead_on_return noundef %{{.*}}) // OLDABI: call void @_ZN11one_deleted3fooENS_1AE(ptr %{{.*}}) -// NEWABI-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(ptr noundef) +// NEWABI-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(ptr dead_on_return noundef) // OLDABI-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(ptr) -// WIN64-LABEL: declare dso_local void @"?foo@one_deleted@@YAXUA@1@@Z"(ptr noundef) +// WIN64-LABEL: declare dso_local void @"?foo@one_deleted@@YAXUA@1@@Z"(ptr dead_on_return noundef) } namespace copy_defaulted { @@ -170,7 +170,7 @@ void bar() { // CHECK: call void @_ZN14move_defaulted3fooENS_1AE(ptr %{{.*}}) // CHECK-LABEL: declare void @_ZN14move_defaulted3fooENS_1AE(ptr) -// WIN64-LABEL: declare dso_local void @"?foo@move_defaulted@@YAXUA@1@@Z"(ptr noundef) +// WIN64-LABEL: declare dso_local void @"?foo@move_defaulted@@YAXUA@1@@Z"(ptr dead_on_return noundef) } namespace trivial_defaulted { @@ -207,12 +207,12 @@ void bar() { } // CHECK-LABEL: define{{.*}} void @_ZN14two_copy_ctors3barEv() // CHECK: call void @_Z{{.*}}C1Ev( -// NEWABI: call void @_ZN14two_copy_ctors3fooENS_1BE(ptr noundef %{{.*}}) +// NEWABI: call void @_ZN14two_copy_ctors3fooENS_1BE(ptr dead_on_return noundef %{{.*}}) // OLDABI: call void @_ZN14two_copy_ctors3fooENS_1BE(ptr noundef byval -// NEWABI-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(ptr noundef) +// NEWABI-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(ptr dead_on_return noundef) // OLDABI-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(ptr noundef byval -// WIN64-LABEL: declare dso_local void @"?foo@two_copy_ctors@@YAXUB@1@@Z"(ptr noundef) +// WIN64-LABEL: declare dso_local void @"?foo@two_copy_ctors@@YAXUB@1@@Z"(ptr dead_on_return noundef) } namespace definition_only { diff --git a/clang/test/CodeGenCXX/wasm-args-returns.cpp b/clang/test/CodeGenCXX/wasm-args-returns.cpp index fbb152ac1bb3d..7b1c27bf0808d 100644 --- a/clang/test/CodeGenCXX/wasm-args-returns.cpp +++ b/clang/test/CodeGenCXX/wasm-args-returns.cpp @@ -46,17 +46,17 @@ struct copy_ctor { copy_ctor(copy_ctor const &); }; test(copy_ctor); -// CHECK: define void @_Z7forward9copy_ctor(ptr dead_on_unwind noalias {{[^,]*}} sret(%struct.copy_ctor) align 8 %{{.*}}, ptr nonnull %{{.*}}) +// CHECK: define void @_Z7forward9copy_ctor(ptr dead_on_unwind noalias {{[^,]*}} sret(%struct.copy_ctor) align 8 %{{.*}}, ptr dead_on_return nonnull %{{.*}}) // // CHECK: declare ptr @_ZN9copy_ctorC1ERKS_(ptr {{[^,]*}} returned {{[^,]*}}, ptr nonnull align 8 dereferenceable(8)) // // CHECK: define void @_Z14test_copy_ctorv() // CHECK: %[[tmp:.*]] = alloca %struct.copy_ctor, align 8 // CHECK: call void @_Z13def_copy_ctorv(ptr dead_on_unwind nonnull writable sret(%struct.copy_ctor) align 8 %[[tmp]]) -// CHECK: call void @_Z3use9copy_ctor(ptr nonnull %[[tmp]]) +// CHECK: call void @_Z3use9copy_ctor(ptr dead_on_return nonnull %[[tmp]]) // CHECK: ret void // -// CHECK: declare void @_Z3use9copy_ctor(ptr) +// CHECK: declare void @_Z3use9copy_ctor(ptr dead_on_return) // CHECK: declare void @_Z13def_copy_ctorv(ptr dead_on_unwind writable sret(%struct.copy_ctor) align 8) struct __attribute__((aligned(16))) aligned_copy_ctor { @@ -64,17 +64,17 @@ struct __attribute__((aligned(16))) aligned_copy_ctor { aligned_copy_ctor(aligned_copy_ctor const &); }; test(aligned_copy_ctor); -// CHECK: define void @_Z7forward17aligned_copy_ctor(ptr dead_on_unwind noalias {{[^,]*}} sret(%struct.aligned_copy_ctor) align 16 %{{.*}}, ptr nonnull %{{.*}}) +// CHECK: define void @_Z7forward17aligned_copy_ctor(ptr dead_on_unwind noalias {{[^,]*}} sret(%struct.aligned_copy_ctor) align 16 %{{.*}}, ptr dead_on_return nonnull %{{.*}}) // // CHECK: declare ptr @_ZN17aligned_copy_ctorC1ERKS_(ptr {{[^,]*}} returned {{[^,]*}}, ptr nonnull align 16 dereferenceable(16)) // // CHECK: define void @_Z22test_aligned_copy_ctorv() // CHECK: %[[tmp:.*]] = alloca %struct.aligned_copy_ctor, align 16 // CHECK: call void @_Z21def_aligned_copy_ctorv(ptr dead_on_unwind nonnull writable sret(%struct.aligned_copy_ctor) align 16 %[[tmp]]) -// CHECK: call void @_Z3use17aligned_copy_ctor(ptr nonnull %[[tmp]]) +// CHECK: call void @_Z3use17aligned_copy_ctor(ptr dead_on_return nonnull %[[tmp]]) // CHECK: ret void // -// CHECK: declare void @_Z3use17aligned_copy_ctor(ptr) +// CHECK: declare void @_Z3use17aligned_copy_ctor(ptr dead_on_return) // CHECK: declare void @_Z21def_aligned_copy_ctorv(ptr dead_on_unwind writable sret(%struct.aligned_copy_ctor) align 16) struct empty {}; diff --git a/clang/test/CodeGenCXX/windows-x86-swiftcall.cpp b/clang/test/CodeGenCXX/windows-x86-swiftcall.cpp index 9927d0b24799e..78c45753b5bbd 100644 --- a/clang/test/CodeGenCXX/windows-x86-swiftcall.cpp +++ b/clang/test/CodeGenCXX/windows-x86-swiftcall.cpp @@ -18,7 +18,7 @@ struct NonTrivial { SWIFTCALL int receiveNonTrivial(NonTrivial o) { return o.o; } -// CHECK-LABEL: define dso_local swiftcc noundef i32 @"?receiveNonTrivial@@YSHUNonTrivial@@@Z"(ptr noundef %o) +// CHECK-LABEL: define dso_local swiftcc noundef i32 @"?receiveNonTrivial@@YSHUNonTrivial@@@Z"(ptr dead_on_return noundef %o) int passNonTrivial() { return receiveNonTrivial({}); @@ -26,4 +26,4 @@ int passNonTrivial() { // CHECK-LABEL: define dso_local noundef i32 @"?passNonTrivial@@YAHXZ"() // CHECK-NOT: stacksave -// CHECK: call swiftcc noundef i32 @"?receiveNonTrivial@@YSHUNonTrivial@@@Z"(ptr noundef %{{.*}}) +// CHECK: call swiftcc noundef i32 @"?receiveNonTrivial@@YSHUNonTrivial@@@Z"(ptr dead_on_return noundef %{{.*}}) diff --git a/clang/test/CodeGenHLSL/builtins/refract.hlsl b/clang/test/CodeGenHLSL/builtins/refract.hlsl new file mode 100644 index 0000000000000..eda256451ee2b --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/refract.hlsl @@ -0,0 +1,244 @@ +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ +// RUN: -emit-llvm -o - | FileCheck %s --check-prefix=SPVCHECK + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) half @_Z17test_refract_halfDhDhDh( +// CHECK-SAME: half noundef nofpclass(nan inf) [[I:%.*]], half noundef nofpclass(nan inf) [[N:%.*]], half noundef nofpclass(nan inf) [[ETA:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK: [[ENTRY:.*:]] +// CHECK: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half %{{.*}}, %{{.*}} +// CHECK: [[MUL1_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half %{{.*}}, %{{.*}} +// CHECK: [[MUL2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half %{{.*}}, %{{.*}} +// CHECK: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half 0xH3C00, [[MUL2_I]] +// CHECK: [[MUL3_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[MUL1_I]], [[SUB_I]] +// CHECK: [[SUB4_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half 0xH3C00, [[MUL3_I]] +// CHECK: [[MUL5_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half %{{.*}}, %{{.*}} +// CHECK: [[MUL6_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half %{{.*}}, %{{.*}} +// CHECK: [[TMP0:%.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.sqrt.f16(half %{{.*}}) +// CHECK: [[ADD_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn half [[MUL6_I]], %{{.*}} +// CHECK: [[MUL7_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[ADD_I]], %{{.*}} +// CHECK: [[SUB8_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half %{{.*}}, [[MUL7_I]] +// CHECK: [[CMP_I:%.*]] = fcmp reassoc nnan ninf nsz arcp afn olt half %{{.*}}, 0xH0000 +// CHECK: [[HLSL_SELECT_I:%.*]] = select reassoc nnan ninf nsz arcp afn i1 [[CMP_I]], half 0xH0000, half %{{.*}} +// CHECK: ret half [[HLSL_SELECT_I]] +// +// SPVCHECK-LABEL: define hidden spir_func noundef nofpclass(nan inf) half @_Z17test_refract_halfDhDhDh( +// SPVCHECK-SAME: half noundef nofpclass(nan inf) [[I:%.*]], half noundef nofpclass(nan inf) [[N:%.*]], half noundef nofpclass(nan inf) [[ETA:%.*]]) #[[ATTR0:[0-9]+]] +// SPVCHECK: [[ENTRY:.*:]] +// SPVCHECK: [[SPV_REFRACT_I:%.*]] = call reassoc nnan ninf nsz arcp afn noundef half @llvm.spv.refract.f16.f16(half %{{.*}}, half %{{.*}}, half %{{.*}}) +// SPVCHECK: ret half [[SPV_REFRACT_I]] +// +half test_refract_half(half I, half N, half ETA) { + return refract(I, N, ETA); +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <2 x half> @_Z18test_refract_half2Dv2_DhS_Dh( +// CHECK-SAME: <2 x half> noundef nofpclass(nan inf) [[I:%.*]], <2 x half> noundef nofpclass(nan inf) [[N:%.*]], half noundef nofpclass(nan inf) [[ETA:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK: [[ENTRY:.*:]] +// CHECK: [[HLSL_DOT_I:%.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.dx.fdot.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}}) +// CHECK: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half %{{.*}}, %{{.*}} +// CHECK: [[MUL3_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x half> %{{.*}}, %{{.*}} +// CHECK: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <2 x half> splat (half 0xH3C00), [[MUL3_I]] +// CHECK: [[MUL4_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x half> %{{.*}}, [[SUB_I]] +// CHECK: [[SUB5_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <2 x half> splat (half 0xH3C00), [[MUL4_I]] +// CHECK: [[MUL8_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x half> %{{.*}}, %{{.*}} +// CHECK: [[MUL11_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x half> %{{.*}}, %{{.*}} +// CHECK: [[TMP17:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x half> @llvm.sqrt.v2f16(<2 x half> %{{.*}}) +// CHECK: [[ADD_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn <2 x half> [[MUL11_I]], [[TMP17]] +// CHECK: [[MUL12_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x half> [[ADD_I]], %{{.*}} +// CHECK: [[SUB13_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <2 x half> [[MUL8_I]], [[MUL12_I]] +// CHECK: [[CMP_I:%.*]] = fcmp reassoc nnan ninf nsz arcp afn olt <2 x half> %{{.*}}, zeroinitializer +// CHECK: [[CAST:%.*]] = extractelement <2 x i1> [[CMP_I]], i32 0 +// CHECK: [[HLSL_SELECT_I:%.*]] = select reassoc nnan ninf nsz arcp afn i1 [[CAST]], <2 x half> zeroinitializer, <2 x half> %{{.*}} +// CHECK: ret <2 x half> [[HLSL_SELECT_I]] +// +// SPVCHECK-LABEL: define hidden spir_func noundef nofpclass(nan inf) <2 x half> @_Z18test_refract_half2Dv2_DhS_Dh( +// SPVCHECK-SAME: <2 x half> noundef nofpclass(nan inf) [[I:%.*]], <2 x half> noundef nofpclass(nan inf) [[N:%.*]], half noundef nofpclass(nan inf) [[ETA:%.*]]) #[[ATTR0:[0-9]+]] { +// SPVCHECK: [[ENTRY:.*:]] +// SPVCHECK: [[SPV_REFRACT_I:%.*]] = call reassoc nnan ninf nsz arcp afn noundef <2 x half> @llvm.spv.refract.v2f16.f16(<2 x half> %{{.*}}, <2 x half> %{{.*}}, half %{{.*}}) +// SPVCHECK: ret <2 x half> [[SPV_REFRACT_I]] +// +half2 test_refract_half2(half2 I, half2 N, half ETA) { + return refract(I, N, ETA); +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x half> @_Z18test_refract_half3Dv3_DhS_Dh( +// CHECK-SAME: <3 x half> noundef nofpclass(nan inf) [[I:%.*]], <3 x half> noundef nofpclass(nan inf) [[N:%.*]], half noundef nofpclass(nan inf) [[ETA:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK: [[ENTRY:.*:]] +// CHECK: [[HLSL_DOT_I:%.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.dx.fdot.v3f16(<3 x half> %{{.*}}, <3 x half> %{{.*}}) +// CHECK: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half %{{.*}}, %{{.*}} +// CHECK: [[MUL3_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x half> %{{.*}}, %{{.*}} +// CHECK: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <3 x half> splat (half 0xH3C00), [[MUL3_I]] +// CHECK: [[MUL4_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x half> %{{.*}}, [[SUB_I]] +// CHECK: [[SUB5_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <3 x half> splat (half 0xH3C00), [[MUL4_I]] +// CHECK: [[MUL8_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x half> %{{.*}}, %{{.*}} +// CHECK: [[MUL11_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x half> %{{.*}}, %{{.*}} +// CHECK: [[TMP17:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x half> @llvm.sqrt.v3f16(<3 x half> %{{.*}}) +// CHECK: [[ADD_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn <3 x half> [[MUL11_I]], [[TMP17]] +// CHECK: [[MUL12_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x half> [[ADD_I]], %{{.*}} +// CHECK: [[SUB13_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <3 x half> [[MUL8_I]], [[MUL12_I]] +// CHECK: [[CMP_I:%.*]] = fcmp reassoc nnan ninf nsz arcp afn olt <3 x half> %{{.*}}, zeroinitializer +// CHECK: [[CAST:%.*]] = extractelement <3 x i1> [[CMP_I]], i32 0 +// CHECK: [[HLSL_SELECT_I:%.*]] = select reassoc nnan ninf nsz arcp afn i1 [[CAST]], <3 x half> zeroinitializer, <3 x half> %{{.*}} +// CHECK: ret <3 x half> [[HLSL_SELECT_I]] +// +// SPVCHECK-LABEL: define hidden spir_func noundef nofpclass(nan inf) <3 x half> @_Z18test_refract_half3Dv3_DhS_Dh( +// SPVCHECK-SAME: <3 x half> noundef nofpclass(nan inf) [[I:%.*]], <3 x half> noundef nofpclass(nan inf) [[N:%.*]], half noundef nofpclass(nan inf) [[ETA:%.*]]) #[[ATTR0:[0-9]+]] { +// SPVCHECK: [[ENTRY:.*:]] +// SPVCHECK: [[SPV_REFRACT_I:%.*]] = call reassoc nnan ninf nsz arcp afn noundef <3 x half> @llvm.spv.refract.v3f16.f16(<3 x half> %{{.*}}, <3 x half> %{{.*}}, half %{{.*}}) +// SPVCHECK: ret <3 x half> [[SPV_REFRACT_I]] +// +half3 test_refract_half3(half3 I, half3 N, half ETA) { + return refract(I, N, ETA); +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x half> @_Z18test_refract_half4Dv4_DhS_Dh( +// CHECK-SAME: <4 x half> noundef nofpclass(nan inf) [[I:%.*]], <4 x half> noundef nofpclass(nan inf) [[N:%.*]], half noundef nofpclass(nan inf) [[ETA:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK: [[ENTRY:.*:]] +// CHECK: [[HLSL_DOT_I:%.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.dx.fdot.v4f16(<4 x half> %{{.*}}, <4 x half> %{{.*}}) +// CHECK: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half %{{.*}}, %{{.*}} +// CHECK: [[MUL3_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x half> %{{.*}}, %{{.*}} +// CHECK: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <4 x half> splat (half 0xH3C00), [[MUL3_I]] +// CHECK: [[MUL4_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x half> %{{.*}}, [[SUB_I]] +// CHECK: [[SUB5_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <4 x half> splat (half 0xH3C00), [[MUL4_I]] +// CHECK: [[MUL8_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x half> %{{.*}}, %{{.*}} +// CHECK: [[MUL11_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x half> %{{.*}}, %{{.*}} +// CHECK: [[TMP17:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x half> @llvm.sqrt.v4f16(<4 x half> %{{.*}}) +// CHECK: [[ADD_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn <4 x half> [[MUL11_I]], [[TMP17]] +// CHECK: [[MUL12_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x half> [[ADD_I]], %{{.*}} +// CHECK: [[SUB13_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <4 x half> [[MUL8_I]], [[MUL12_I]] +// CHECK: [[CMP_I:%.*]] = fcmp reassoc nnan ninf nsz arcp afn olt <4 x half> %{{.*}}, zeroinitializer +// CHECK: [[CAST:%.*]] = extractelement <4 x i1> [[CMP_I]], i32 0 +// CHECK: [[HLSL_SELECT_I:%.*]] = select reassoc nnan ninf nsz arcp afn i1 [[CAST]], <4 x half> zeroinitializer, <4 x half> %{{.*}} +// CHECK: ret <4 x half> [[HLSL_SELECT_I]] +// +// SPVCHECK-LABEL: define hidden spir_func noundef nofpclass(nan inf) <4 x half> @_Z18test_refract_half4Dv4_DhS_Dh( +// SPVCHECK-SAME: <4 x half> noundef nofpclass(nan inf) [[I:%.*]], <4 x half> noundef nofpclass(nan inf) [[N:%.*]], half noundef nofpclass(nan inf) [[ETA:%.*]]) #[[ATTR0:[0-9]+]] { +// SPVCHECK: [[ENTRY:.*:]] +// SPVCHECK: [[SPV_REFRACT_I:%.*]] = call reassoc nnan ninf nsz arcp afn noundef <4 x half> @llvm.spv.refract.v4f16.f16(<4 x half> %{{.*}}, <4 x half> %{{.*}}, half %{{.*}}) +// SPVCHECK: ret <4 x half> [[SPV_REFRACT_I]] +// +half4 test_refract_half4(half4 I, half4 N, half ETA) { + return refract(I, N, ETA); +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z18test_refract_floatfff( +// CHECK-SAME: float noundef nofpclass(nan inf) [[I:%.*]], float noundef nofpclass(nan inf) [[N:%.*]], float noundef nofpclass(nan inf) [[ETA:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK: [[ENTRY:.*:]] +// CHECK: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float %{{.*}}, %{{.*}} +// CHECK: [[MUL1_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float %{{.*}}, %{{.*}} +// CHECK: [[MUL2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float %{{.*}}, %{{.*}} +// CHECK: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float 1.000000e+00, [[MUL2_I]] +// CHECK: [[MUL3_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[MUL1_I]], [[SUB_I]] +// CHECK: [[SUB4_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float 1.000000e+00, [[MUL3_I]] +// CHECK: [[MUL5_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float %{{.*}}, %{{.*}} +// CHECK: [[MUL6_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float %{{.*}}, %{{.*}} +// CHECK: [[TMP17:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.sqrt.f32(float %{{.*}}) +// CHECK: [[ADD_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[MUL6_I]], %{{.*}} +// CHECK: [[MUL7_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[ADD_I]], %{{.*}} +// CHECK: [[SUB8_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float %{{.*}}, [[MUL7_I]] +// CHECK: [[CMP_I:%.*]] = fcmp reassoc nnan ninf nsz arcp afn olt float %{{.*}}, 0.000000e+00 +// CHECK: [[HLSL_SELECT_I:%.*]] = select reassoc nnan ninf nsz arcp afn i1 [[CMP_I]], float 0.000000e+00, float %{{.*}} +// CHECK: ret float [[HLSL_SELECT_I]] +// +// SPVCHECK-LABEL: define hidden spir_func noundef nofpclass(nan inf) float @_Z18test_refract_floatfff( +// SPVCHECK-SAME: float noundef nofpclass(nan inf) [[I:%.*]], float noundef nofpclass(nan inf) [[N:%.*]], float noundef nofpclass(nan inf) [[ETA:%.*]]) #[[ATTR0:[0-9]+]] { +// SPVCHECK: [[ENTRY:.*:]] +// SPVCHECK: [[SPV_REFRACT_I:%.*]] = call reassoc nnan ninf nsz arcp afn noundef float @llvm.spv.refract.f32.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}) +// SPVCHECK: ret float [[SPV_REFRACT_I]] +// +float test_refract_float(float I, float N, float ETA) { + return refract(I, N, ETA); +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> @_Z19test_refract_float2Dv2_fS_f( +// CHECK-SAME: <2 x float> noundef nofpclass(nan inf) [[I:%.*]], <2 x float> noundef nofpclass(nan inf) [[N:%.*]], float noundef nofpclass(nan inf) [[ETA:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK: [[ENTRY:.*:]] +// CHECK: [[HLSL_DOT_I:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}}) +// CHECK: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float %{{.*}}, %{{.*}} +// CHECK: [[MUL3_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x float> %{{.*}}, %{{.*}} +// CHECK: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <2 x float> splat (float 1.000000e+00), [[MUL3_I]] +// CHECK: [[MUL4_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x float> %{{.*}}, [[SUB_I]] +// CHECK: [[SUB5_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <2 x float> splat (float 1.000000e+00), [[MUL4_I]] +// CHECK: [[MUL8_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x float> %{{.*}}, %{{.*}} +// CHECK: [[MUL11_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x float> %{{.*}}, %{{.*}} +// CHECK: [[TMP17:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.sqrt.v2f32(<2 x float> %{{.*}}) +// CHECK: [[ADD_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn <2 x float> [[MUL11_I]], [[TMP17]] +// CHECK: [[MUL12_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x float> [[ADD_I]], %{{.*}} +// CHECK: [[SUB13_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <2 x float> [[MUL8_I]], [[MUL12_I]] +// CHECK: [[CMP_I:%.*]] = fcmp reassoc nnan ninf nsz arcp afn olt <2 x float> %{{.*}}, zeroinitializer +// CHECK: [[CAST:%.*]] = extractelement <2 x i1> [[CMP_I]], i32 0 +// CHECK: [[HLSL_SELECT_I:%.*]] = select reassoc nnan ninf nsz arcp afn i1 [[CAST]], <2 x float> zeroinitializer, <2 x float> %{{.*}} +// CHECK: ret <2 x float> [[HLSL_SELECT_I]] +// +// SPVCHECK-LABEL: define hidden spir_func noundef nofpclass(nan inf) <2 x float> @_Z19test_refract_float2Dv2_fS_f( +// SPVCHECK-SAME: <2 x float> noundef nofpclass(nan inf) [[I:%.*]], <2 x float> noundef nofpclass(nan inf) [[N:%.*]], float noundef nofpclass(nan inf) [[ETA:%.*]]) #[[ATTR0:[0-9]+]] { +// SPVCHECK: [[ENTRY:.*:]] +// SPVCHECK: [[SPV_REFRACT_I:%.*]] = call reassoc nnan ninf nsz arcp afn noundef <2 x float> @llvm.spv.refract.v2f32.f32(<2 x float> %{{.*}}, <2 x float> %{{.*}}, float %{{.*}}) +// SPVCHECK: ret <2 x float> [[SPV_REFRACT_I]] +// +float2 test_refract_float2(float2 I, float2 N, float ETA) { + return refract(I, N, ETA); +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> @_Z19test_refract_float3Dv3_fS_f( +// CHECK-SAME: <3 x float> noundef nofpclass(nan inf) [[I:%.*]], <3 x float> noundef nofpclass(nan inf) [[N:%.*]], float noundef nofpclass(nan inf) [[ETA:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK: [[HLSL_DOT_I:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}}) +// CHECK: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float %{{.*}}, %{{.*}} +// CHECK: [[MUL3_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x float> %{{.*}}, %{{.*}} +// CHECK: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <3 x float> splat (float 1.000000e+00), [[MUL3_I]] +// CHECK: [[MUL4_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x float> %{{.*}}, [[SUB_I]] +// CHECK: [[SUB5_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <3 x float> splat (float 1.000000e+00), [[MUL4_I]] +// CHECK: [[MUL8_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x float> %{{.*}}, %{{.*}} +// CHECK: [[MUL11_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x float> %{{.*}}, %{{.*}} +// CHECK: [[TMP17:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.sqrt.v3f32(<3 x float> %{{.*}}) +// CHECK: [[ADD_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn <3 x float> [[MUL11_I]], [[TMP17]] +// CHECK: [[MUL12_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x float> [[ADD_I]], %{{.*}} +// CHECK: [[SUB13_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <3 x float> [[MUL8_I]], [[MUL12_I]] +// CHECK: [[CMP_I:%.*]] = fcmp reassoc nnan ninf nsz arcp afn olt <3 x float> %{{.*}}, zeroinitializer +// CHECK: [[CAST:%.*]] = extractelement <3 x i1> [[CMP_I]], i32 0 +// CHECK: [[HLSL_SELECT_I:%.*]] = select reassoc nnan ninf nsz arcp afn i1 [[CAST]], <3 x float> zeroinitializer, <3 x float> %{{.*}} +// CHECK: ret <3 x float> [[HLSL_SELECT_I]] +// +// SPVCHECK-LABEL: define hidden spir_func noundef nofpclass(nan inf) <3 x float> @_Z19test_refract_float3Dv3_fS_f( +// SPVCHECK-SAME: <3 x float> noundef nofpclass(nan inf) [[I:%.*]], <3 x float> noundef nofpclass(nan inf) [[N:%.*]], float noundef nofpclass(nan inf) [[ETA:%.*]]) #[[ATTR0:[0-9]+]] { +// SPVCHECK: [[ENTRY:.*:]] +// SPVCHECK: [[SPV_REFRACT_I:%.*]] = call reassoc nnan ninf nsz arcp afn noundef <3 x float> @llvm.spv.refract.v3f32.f32(<3 x float> %{{.*}}, <3 x float> %{{.*}}, float %{{.*}}) +// SPVCHECK: ret <3 x float> [[SPV_REFRACT_I]] +// +float3 test_refract_float3(float3 I, float3 N, float ETA) { + return refract(I, N, ETA); +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> @_Z19test_refract_float4Dv4_fS_f +// CHECK-SAME: <4 x float> noundef nofpclass(nan inf) [[I:%.*]], <4 x float> noundef nofpclass(nan inf) [[N:%.*]], float noundef nofpclass(nan inf) [[ETA:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK: [[HLSL_DOT_I:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}) +// CHECK: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float %{{.*}}, %{{.*}} +// CHECK: [[MUL3_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x float> %{{.*}}, %{{.*}} +// CHECK: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <4 x float> splat (float 1.000000e+00), [[MUL3_I]] +// CHECK: [[MUL4_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x float> %{{.*}}, [[SUB_I]] +// CHECK: [[SUB5_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <4 x float> splat (float 1.000000e+00), [[MUL4_I]] +// CHECK: [[MUL8_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x float> %{{.*}}, %{{.*}} +// CHECK: [[MUL11_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x float> %{{.*}}, %{{.*}} +// CHECK: [[TMP17:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.sqrt.v4f32(<4 x float> %{{.*}}) +// CHECK: [[ADD_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn <4 x float> [[MUL11_I]], [[TMP17]] +// CHECK: [[MUL12_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x float> [[ADD_I]], %{{.*}} +// CHECK: [[SUB13_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <4 x float> [[MUL8_I]], [[MUL12_I]] +// CHECK: [[CMP_I:%.*]] = fcmp reassoc nnan ninf nsz arcp afn olt <4 x float> %{{.*}}, zeroinitializer +// CHECK: [[CAST:%.*]] = extractelement <4 x i1> [[CMP_I]], i32 0 +// CHECK: [[HLSL_SELECT_I:%.*]] = select reassoc nnan ninf nsz arcp afn i1 [[CAST]], <4 x float> zeroinitializer, <4 x float> %{{.*}} +// CHECK: ret <4 x float> [[HLSL_SELECT_I]] + +// SPVCHECK-LABEL: define hidden spir_func noundef nofpclass(nan inf) <4 x float> @_Z19test_refract_float4Dv4_fS_f( +// SPVCHECK-SAME: <4 x float> noundef nofpclass(nan inf) %{{.*}}, <4 x float> noundef nofpclass(nan inf) %{{.*}}, float noundef nofpclass(nan inf) %{{.*}}) #[[ATTR0:[0-9]+]] { +// SPVCHECK: [[ENTRY:.*:]] +// SPVCHECK: [[SPV_REFRACT_I:%.*]] = call reassoc nnan ninf nsz arcp afn noundef <4 x float> @llvm.spv.refract.v4f32.f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, float %{{.*}}) +// SPVCHECK: ret <4 x float> [[SPV_REFRACT_I]] +// +float4 test_refract_float4(float4 I, float4 N, float ETA) { + return refract(I, N, ETA); +} diff --git a/clang/test/CodeGenObjC/nontrivial-c-struct-exception.m b/clang/test/CodeGenObjC/nontrivial-c-struct-exception.m index d2a954ae26a04..ba8a04b52716e 100644 --- a/clang/test/CodeGenObjC/nontrivial-c-struct-exception.m +++ b/clang/test/CodeGenObjC/nontrivial-c-struct-exception.m @@ -42,7 +42,7 @@ void testStrongException(void) { // CHECK: call void @genWeak(ptr dead_on_unwind writable sret(%[[STRUCT_WEAK]]) align 8 %[[AGG_TMP]]) // CHECK: invoke void @genWeak(ptr dead_on_unwind writable sret(%[[STRUCT_WEAK]]) align 8 %[[AGG_TMP1]]) -// CHECK: call void @calleeWeak(ptr noundef %[[AGG_TMP]], ptr noundef %[[AGG_TMP1]]) +// CHECK: call void @calleeWeak(ptr dead_on_return noundef %[[AGG_TMP]], ptr dead_on_return noundef %[[AGG_TMP1]]) // CHECK: ret void // CHECK: landingpad { ptr, i32 } diff --git a/clang/test/CodeGenObjC/pass-by-value-noalias.m b/clang/test/CodeGenObjC/pass-by-value-noalias.m index ed94d4c80b525..86a4ba36a1b8f 100644 --- a/clang/test/CodeGenObjC/pass-by-value-noalias.m +++ b/clang/test/CodeGenObjC/pass-by-value-noalias.m @@ -17,6 +17,6 @@ @interface Bar Bar *__weak f; }; -// WITH_NOALIAS: define{{.*}} void @take(ptr noundef %arg) -// NO_NOALIAS: define{{.*}} void @take(ptr noundef %arg) +// WITH_NOALIAS: define{{.*}} void @take(ptr dead_on_return noundef %arg) +// NO_NOALIAS: define{{.*}} void @take(ptr dead_on_return noundef %arg) void take(struct Foo arg) {} diff --git a/clang/test/CodeGenObjC/weak-in-c-struct.m b/clang/test/CodeGenObjC/weak-in-c-struct.m index be80edd1ff11d..6809360d03da1 100644 --- a/clang/test/CodeGenObjC/weak-in-c-struct.m +++ b/clang/test/CodeGenObjC/weak-in-c-struct.m @@ -130,7 +130,7 @@ void test_move_assignment_Weak(Weak *p) { *p = getWeak(); } -// COMMON: define{{.*}} void @test_parameter_Weak(ptr noundef %[[A:.*]]) +// COMMON: define{{.*}} void @test_parameter_Weak(ptr dead_on_return noundef %[[A:.*]]) // COMMON: call void @__destructor_{{.*}}(ptr %[[A]]) void test_parameter_Weak(Weak a) { @@ -142,7 +142,7 @@ void test_parameter_Weak(Weak a) { // COMMON: store ptr %[[A]], ptr %[[A_ADDR]] // COMMON: %[[V0:.*]] = load ptr, ptr %[[A_ADDR]] // COMMON: call void @__copy_constructor_{{.*}}(ptr %[[AGG_TMP]], ptr %[[V0]]) -// COMMON: call void @calleeWeak(ptr noundef %[[AGG_TMP]]) +// COMMON: call void @calleeWeak(ptr dead_on_return noundef %[[AGG_TMP]]) // COMMON-NEXT: ret void test_argument_Weak(Weak *a) { @@ -164,7 +164,7 @@ Weak test_return_Weak(Weak *a) { // COMMON: %[[AGG_TMP:.*]] = alloca %[[STRUCT_WEAK]] // COMMON: br i1 -// COMMON: call void @objc_msgSend({{.*}}, ptr noundef %[[AGG_TMP]]) +// COMMON: call void @objc_msgSend({{.*}}, ptr dead_on_return noundef %[[AGG_TMP]]) // COMMON: br // COMMON: call void @__destructor_{{.*}}(ptr %[[AGG_TMP]]) diff --git a/clang/test/CodeGenObjCXX/objc-struct-cxx-abi.mm b/clang/test/CodeGenObjCXX/objc-struct-cxx-abi.mm index 4d76796d86d1f..3a043c4892981 100644 --- a/clang/test/CodeGenObjCXX/objc-struct-cxx-abi.mm +++ b/clang/test/CodeGenObjCXX/objc-struct-cxx-abi.mm @@ -75,7 +75,7 @@ - (void)passStrongWeak:(StrongWeak)a; - (void)passNonTrivial:(NonTrivial)a; @end -// CHECK: define{{.*}} void @_Z19testParamStrongWeak10StrongWeak(ptr noundef %{{.*}}) +// CHECK: define{{.*}} void @_Z19testParamStrongWeak10StrongWeak(ptr dead_on_return noundef %{{.*}}) // CHECK: call noundef ptr @_ZN10StrongWeakD1Ev( // CHECK-NEXT: ret void @@ -88,7 +88,7 @@ void testParamStrongWeak(StrongWeak a) { // CHECK: store ptr %[[A]], ptr %[[A_ADDR]], align 8 // CHECK: %[[V0:.*]] = load ptr, ptr %[[A_ADDR]], align 8 // CHECK: %[[CALL:.*]] = call noundef ptr @_ZN10StrongWeakC1ERKS_(ptr {{[^,]*}} %[[AGG_TMP]], ptr noundef nonnull align 8 dereferenceable(16) %[[V0]]) -// CHECK: call void @_Z19testParamStrongWeak10StrongWeak(ptr noundef %[[AGG_TMP]]) +// CHECK: call void @_Z19testParamStrongWeak10StrongWeak(ptr dead_on_return noundef %[[AGG_TMP]]) // CHECK-NOT: call // CHECK: ret void @@ -107,13 +107,13 @@ StrongWeak testReturnStrongWeak(StrongWeak *a) { return *a; } -// CHECK: define{{.*}} void @_Z27testParamContainsStrongWeak18ContainsStrongWeak(ptr noundef %[[A:.*]]) +// CHECK: define{{.*}} void @_Z27testParamContainsStrongWeak18ContainsStrongWeak(ptr dead_on_return noundef %[[A:.*]]) // CHECK: call noundef ptr @_ZN18ContainsStrongWeakD1Ev(ptr {{[^,]*}} %[[A]]) void testParamContainsStrongWeak(ContainsStrongWeak a) { } -// CHECK: define{{.*}} void @_Z26testParamDerivedStrongWeak17DerivedStrongWeak(ptr noundef %[[A:.*]]) +// CHECK: define{{.*}} void @_Z26testParamDerivedStrongWeak17DerivedStrongWeak(ptr dead_on_return noundef %[[A:.*]]) // CHECK: call noundef ptr @_ZN17DerivedStrongWeakD1Ev(ptr {{[^,]*}} %[[A]]) void testParamDerivedStrongWeak(DerivedStrongWeak a) { @@ -163,7 +163,7 @@ Strong testReturnStrong(Strong *a) { return *a; } -// CHECK: define{{.*}} void @_Z21testParamWeakTemplate1SIU6__weakP11objc_objectE(ptr noundef %{{.*}}) +// CHECK: define{{.*}} void @_Z21testParamWeakTemplate1SIU6__weakP11objc_objectE(ptr dead_on_return noundef %{{.*}}) // CHECK: call noundef ptr @_ZN1SIU6__weakP11objc_objectED1Ev( // CHECK-NEXT: ret void @@ -237,7 +237,7 @@ void test0(C *c) { // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONGWEAK]], align 8 // CHECK: br i1 -// CHECK: call void @objc_msgSend({{.*}}, ptr noundef %[[AGG_TMP]]) +// CHECK: call void @objc_msgSend({{.*}}, ptr dead_on_return noundef %[[AGG_TMP]]) // CHECK: br // CHECK: %[[CALL1:.*]] = call noundef ptr @_ZN10StrongWeakD1Ev(ptr noundef nonnull align 8 dereferenceable(16) %[[AGG_TMP]]) diff --git a/clang/test/CodeGenObjCXX/property-objects.mm b/clang/test/CodeGenObjCXX/property-objects.mm index 7ae20f66177bd..8354794254933 100644 --- a/clang/test/CodeGenObjCXX/property-objects.mm +++ b/clang/test/CodeGenObjCXX/property-objects.mm @@ -60,7 +60,7 @@ - (struct CGRect)extent {return bounds;} // CHECK-LABEL: define{{.*}} i32 @main // CHECK: call void @_ZN1SC1ERKS_(ptr {{[^,]*}} [[AGGTMP:%[a-zA-Z0-9\.]+]], ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) {{%[a-zA-Z0-9\.]+}}) -// CHECK: call void @objc_msgSend(ptr noundef {{%[a-zA-Z0-9\.]+}}, ptr noundef {{%[a-zA-Z0-9\.]+}}, ptr noundef [[AGGTMP]]) +// CHECK: call void @objc_msgSend(ptr noundef {{%[a-zA-Z0-9\.]+}}, ptr noundef {{%[a-zA-Z0-9\.]+}}, ptr dead_on_return noundef [[AGGTMP]]) // CHECK-NEXT: ret i32 0 int main() { I *i; diff --git a/clang/test/CodeGenObjCXX/ptrauth-struct-cxx-abi.mm b/clang/test/CodeGenObjCXX/ptrauth-struct-cxx-abi.mm index e5cb71bad47c0..9428940d6da48 100644 --- a/clang/test/CodeGenObjCXX/ptrauth-struct-cxx-abi.mm +++ b/clang/test/CodeGenObjCXX/ptrauth-struct-cxx-abi.mm @@ -15,7 +15,7 @@ // Check that AddrDiscStrong0 is destructed in the callee. -// CHECK: define void @_Z24testParamAddrDiscStrong015AddrDiscStrong0(ptr noundef %[[A:.*]]) +// CHECK: define void @_Z24testParamAddrDiscStrong015AddrDiscStrong0(ptr dead_on_return noundef %[[A:.*]]) // CHECK: call noundef ptr @_ZN15AddrDiscStrong0D1Ev(ptr noundef nonnull align {{[0-9]+}} dereferenceable(16) %[[A]]) // CHECK: ret void diff --git a/clang/test/CodeGenOpenCL/amdgpu-features.cl b/clang/test/CodeGenOpenCL/amdgpu-features.cl index 42768ac8def1f..75e9710f96705 100644 --- a/clang/test/CodeGenOpenCL/amdgpu-features.cl +++ b/clang/test/CodeGenOpenCL/amdgpu-features.cl @@ -108,7 +108,7 @@ // GFX1153: "target-features"="+16-bit-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot10-insts,+dot12-insts,+dot5-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32" // GFX1200: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-buffer-pk-add-bf16-inst,+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,+dot10-insts,+dot11-insts,+dot12-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+fp8-conversion-insts,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx12-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32" // GFX1201: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-buffer-pk-add-bf16-inst,+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,+dot10-insts,+dot11-insts,+dot12-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+fp8-conversion-insts,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx12-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32" -// GFX1250: "target-features"="+16-bit-insts,+ashr-pk-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-buffer-pk-add-bf16-inst,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+bf16-trans-insts,+bitop3-insts,+ci-insts,+dl-insts,+dot7-insts,+dot8-insts,+dpp,+fp8-conversion-insts,+fp8e5m3-insts,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx12-insts,+gfx1250-insts,+gfx8-insts,+gfx9-insts,+permlane16-swap,+prng-inst,+setprio-inc-wg-inst,+transpose-load-f4f6-insts,+wavefrontsize32" +// GFX1250: "target-features"="+16-bit-insts,+ashr-pk-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-buffer-pk-add-bf16-inst,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+bf16-trans-insts,+bitop3-insts,+ci-insts,+dl-insts,+dot7-insts,+dot8-insts,+dpp,+fp8-conversion-insts,+fp8e5m3-insts,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx12-insts,+gfx1250-insts,+gfx8-insts,+gfx9-insts,+permlane16-swap,+prng-inst,+setprio-inc-wg-inst,+tanh-insts,+transpose-load-f4f6-insts,+wavefrontsize32 // GFX1103-W64: "target-features"="+16-bit-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot10-insts,+dot12-insts,+dot5-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize64" diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250-wmma-w32.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250-wmma-w32.cl index e4ef3defdb341..86c27d48ab0d4 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250-wmma-w32.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250-wmma-w32.cl @@ -157,6 +157,18 @@ void test_amdgcn_wmma_i32_16x16x64_iu8(global v8i* out, v8i a, v8i b, v8i c) *out = __builtin_amdgcn_wmma_i32_16x16x64_iu8(0, a, 0, b, c, false, true); } +// CHECK-GFX1250-LABEL: @test_amdgcn_wmma_f32_16x16x128_f8f6f4( +// CHECK-GFX1250-NEXT: entry: +// CHECK-GFX1250-NEXT: [[TMP0:%.*]] = shufflevector <16 x i32> [[B:%.*]], <16 x i32> poison, <12 x i32> +// CHECK-GFX1250-NEXT: [[TMP1:%.*]] = tail call <8 x float> @llvm.amdgcn.wmma.f32.16x16x128.f8f6f4.v8f32.v16i32.v12i32(i32 1, <16 x i32> [[A:%.*]], i32 2, <12 x i32> [[TMP0]], i16 0, <8 x float> [[C:%.*]]) +// CHECK-GFX1250-NEXT: store <8 x float> [[TMP1]], ptr addrspace(1) [[OUT:%.*]], align 32, !tbaa [[TBAA4]] +// CHECK-GFX1250-NEXT: ret void +// +void test_amdgcn_wmma_f32_16x16x128_f8f6f4(global v8f* out, v16i a, v16i b, v8f c) +{ + *out = __builtin_amdgcn_wmma_f32_16x16x128_f8f6f4(1, a, 2, b, 0, c); +} + // CHECK-GFX1250-LABEL: @test_amdgcn_wmma_f32_16x16x32_f16( // CHECK-GFX1250-NEXT: entry: // CHECK-GFX1250-NEXT: [[TMP0:%.*]] = tail call <8 x float> @llvm.amdgcn.wmma.f32.16x16x32.f16.v8f32.v16f16(i1 false, <16 x half> [[A:%.*]], i1 false, <16 x half> [[B:%.*]], i16 0, <8 x float> [[C:%.*]], i1 false, i1 true) diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250.cl index e50f02ad27357..a21862c4a9395 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250.cl @@ -4,6 +4,9 @@ #pragma OPENCL EXTENSION cl_khr_fp16 : enable +typedef unsigned int uint; +typedef unsigned short int ushort; +typedef unsigned int __attribute__((ext_vector_type(2))) uint2; typedef half __attribute__((ext_vector_type(2))) half2; // CHECK-LABEL: @test_setprio_inc_wg( @@ -42,6 +45,63 @@ void test_s_wait_tensorcnt() { __builtin_amdgcn_s_wait_tensorcnt(0); } +// 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: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(1) [[OUT:%.*]], ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.amdgcn.prng.b32(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], 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); +} + +// CHECK-LABEL: @test_tanh_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca float, align 4, addrspace(5) +// CHECK-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(1) [[OUT:%.*]], ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store float [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.amdgcn.tanh.f32(float [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store float [[TMP1]], ptr addrspace(1) [[TMP2]], align 4 +// CHECK-NEXT: ret void +// +void test_tanh_f32(global float* out, float a) +{ + *out = __builtin_amdgcn_tanhf(a); +} + +// CHECK-LABEL: @test_tanh_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) +// CHECK-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(1) [[OUT:%.*]], ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store ptr addrspace(1) [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr [[A_ADDR_ASCAST]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load half, ptr addrspace(1) [[TMP0]], align 2 +// CHECK-NEXT: [[TMP2:%.*]] = call half @llvm.amdgcn.tanh.f16(half [[TMP1]]) +// CHECK-NEXT: [[TMP3:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store half [[TMP2]], ptr addrspace(1) [[TMP3]], align 2 +// CHECK-NEXT: ret void +// +void test_tanh_f16(global half* out, global half* a) +{ + *out = __builtin_amdgcn_tanhh(*a); +} + // CHECK-LABEL: @test_tanh_bf16( // CHECK-NEXT: entry: // CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) @@ -80,6 +140,120 @@ void test_rcp_bf16(global __bf16* out, __bf16 a) *out = __builtin_amdgcn_rcp_bf16(a); } +// CHECK-LABEL: @test_sqrt_bf16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca bfloat, align 2, addrspace(5) +// CHECK-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(1) [[OUT:%.*]], ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store bfloat [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = call bfloat @llvm.amdgcn.sqrt.bf16(bfloat [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store bfloat [[TMP1]], ptr addrspace(1) [[TMP2]], align 2 +// CHECK-NEXT: ret void +// +void test_sqrt_bf16(global __bf16* out, __bf16 a) +{ + *out = __builtin_amdgcn_sqrt_bf16(a); +} + +// CHECK-LABEL: @test_rsq_bf16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca bfloat, align 2, addrspace(5) +// CHECK-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(1) [[OUT:%.*]], ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store bfloat [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = call bfloat @llvm.amdgcn.rsq.bf16(bfloat [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store bfloat [[TMP1]], ptr addrspace(1) [[TMP2]], align 2 +// CHECK-NEXT: ret void +// +void test_rsq_bf16(global __bf16* out, __bf16 a) +{ + *out = __builtin_amdgcn_rsq_bf16(a); +} + +// CHECK-LABEL: @test_log_bf16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca bfloat, align 2, addrspace(5) +// CHECK-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(1) [[OUT:%.*]], ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store bfloat [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = call bfloat @llvm.amdgcn.log.bf16(bfloat [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store bfloat [[TMP1]], ptr addrspace(1) [[TMP2]], align 2 +// CHECK-NEXT: ret void +// +void test_log_bf16(global __bf16* out, __bf16 a) +{ + *out = __builtin_amdgcn_log_bf16(a); +} + +// CHECK-LABEL: @test_exp2_bf16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca bfloat, align 2, addrspace(5) +// CHECK-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(1) [[OUT:%.*]], ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store bfloat [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = call bfloat @llvm.amdgcn.exp2.bf16(bfloat [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store bfloat [[TMP1]], ptr addrspace(1) [[TMP2]], align 2 +// CHECK-NEXT: ret void +// +void test_exp2_bf16(global __bf16* out, __bf16 a) +{ + *out = __builtin_amdgcn_exp2_bf16(a); +} + +// CHECK-LABEL: @test_sin_bf16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca bfloat, align 2, addrspace(5) +// CHECK-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(1) [[OUT:%.*]], ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store bfloat [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = call bfloat @llvm.amdgcn.sin.bf16(bfloat [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store bfloat [[TMP1]], ptr addrspace(1) [[TMP2]], align 2 +// CHECK-NEXT: ret void +// +void test_sin_bf16(global __bf16* out, __bf16 a) +{ + *out = __builtin_amdgcn_sin_bf16(a); +} + +// CHECK-LABEL: @test_cos_bf16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca bfloat, align 2, addrspace(5) +// CHECK-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(1) [[OUT:%.*]], ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store bfloat [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = call bfloat @llvm.amdgcn.cos.bf16(bfloat [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store bfloat [[TMP1]], ptr addrspace(1) [[TMP2]], align 2 +// CHECK-NEXT: ret void +// +void test_cos_bf16(global __bf16* out, __bf16 a) +{ + *out = __builtin_amdgcn_cos_bf16(a); +} + // CHECK-LABEL: @test_cvt_f16_fp8( // CHECK-NEXT: entry: // CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) @@ -196,6 +370,76 @@ void test_cvt_pk_f16_bf8(global half2* out, short a) out[0] = __builtin_amdgcn_cvt_pk_f16_bf8(a); } +// CHECK-LABEL: @test_sat_pk4_i4_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) +// CHECK-NEXT: [[SRC_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// CHECK-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// CHECK-NEXT: [[SRC_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[SRC_ADDR]] to ptr +// CHECK-NEXT: store ptr [[OUT:%.*]], ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store i32 [[SRC:%.*]], ptr [[SRC_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[SRC_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.amdgcn.sat.pk4.i4.i8(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store i16 [[TMP1]], ptr [[TMP2]], align 2 +// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[SRC_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP4:%.*]] = call i16 @llvm.amdgcn.sat.pk4.u4.u8(i32 [[TMP3]]) +// CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store i16 [[TMP4]], ptr [[TMP5]], align 2 +// CHECK-NEXT: ret void +// +void test_sat_pk4_i4_i8(ushort *out, uint src) +{ + *out = __builtin_amdgcn_sat_pk4_i4_i8(src); + *out = __builtin_amdgcn_sat_pk4_u4_u8(src); +} + +// CHECK-LABEL: @test_permlane16_swap( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) +// CHECK-NEXT: [[OLD_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// CHECK-NEXT: [[SRC_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// CHECK-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// CHECK-NEXT: [[OLD_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OLD_ADDR]] to ptr +// CHECK-NEXT: [[SRC_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[SRC_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(1) [[OUT:%.*]], ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store i32 [[OLD:%.*]], ptr [[OLD_ADDR_ASCAST]], align 4 +// CHECK-NEXT: store i32 [[SRC:%.*]], ptr [[SRC_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[OLD_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[SRC_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = call { i32, i32 } @llvm.amdgcn.permlane16.swap(i32 [[TMP0]], i32 [[TMP1]], i1 false, i1 false) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i32 } [[TMP2]], 0 +// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i32, i32 } [[TMP2]], 1 +// CHECK-NEXT: [[TMP5:%.*]] = insertelement <2 x i32> poison, i32 [[TMP3]], i64 0 +// CHECK-NEXT: [[TMP6:%.*]] = insertelement <2 x i32> [[TMP5]], i32 [[TMP4]], i64 1 +// CHECK-NEXT: [[TMP7:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store <2 x i32> [[TMP6]], ptr addrspace(1) [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr [[OLD_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[SRC_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP10:%.*]] = call { i32, i32 } @llvm.amdgcn.permlane16.swap(i32 [[TMP8]], i32 [[TMP9]], i1 true, i1 false) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { i32, i32 } [[TMP10]], 0 +// CHECK-NEXT: [[TMP12:%.*]] = extractvalue { i32, i32 } [[TMP10]], 1 +// CHECK-NEXT: [[TMP13:%.*]] = insertelement <2 x i32> poison, i32 [[TMP11]], i64 0 +// CHECK-NEXT: [[TMP14:%.*]] = insertelement <2 x i32> [[TMP13]], i32 [[TMP12]], i64 1 +// CHECK-NEXT: [[TMP15:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store <2 x i32> [[TMP14]], ptr addrspace(1) [[TMP15]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load i32, ptr [[OLD_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP17:%.*]] = load i32, ptr [[SRC_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP18:%.*]] = call { i32, i32 } @llvm.amdgcn.permlane16.swap(i32 [[TMP16]], i32 [[TMP17]], i1 false, i1 true) +// CHECK-NEXT: [[TMP19:%.*]] = extractvalue { i32, i32 } [[TMP18]], 0 +// CHECK-NEXT: [[TMP20:%.*]] = extractvalue { i32, i32 } [[TMP18]], 1 +// CHECK-NEXT: [[TMP21:%.*]] = insertelement <2 x i32> poison, i32 [[TMP19]], i64 0 +// CHECK-NEXT: [[TMP22:%.*]] = insertelement <2 x i32> [[TMP21]], i32 [[TMP20]], i64 1 +// CHECK-NEXT: [[TMP23:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store <2 x i32> [[TMP22]], ptr addrspace(1) [[TMP23]], align 8 +// CHECK-NEXT: ret void +// +void test_permlane16_swap(global uint2* out, uint old, uint src) { + *out = __builtin_amdgcn_permlane16_swap(old, src, false, false); + *out = __builtin_amdgcn_permlane16_swap(old, src, true, false); + *out = __builtin_amdgcn_permlane16_swap(old, src, false, true); +} + // CHECK-LABEL: @test_cvt_f32_fp8_e5m3( // CHECK-NEXT: entry: // CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-raw-buffer-load-lds.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-raw-buffer-load-lds.cl index 8256b61525f9d..177165972b7a9 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-raw-buffer-load-lds.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-raw-buffer-load-lds.cl @@ -10,3 +10,12 @@ void test_amdgcn_raw_ptr_buffer_load_lds(__amdgpu_buffer_rsrc_t rsrc, __local void * lds, int offset, int soffset) { __builtin_amdgcn_raw_ptr_buffer_load_lds(rsrc, lds, 1, offset, soffset, 2, 3); } + +// CHECK-LABEL: @test_amdgcn_struct_ptr_buffer_load_lds( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.amdgcn.struct.ptr.buffer.load.lds(ptr addrspace(8) [[RSRC:%.*]], ptr addrspace(3) [[LDS:%.*]], i32 4, i32 [[VINDEX:%.*]], i32 [[VOFFSET:%.*]], i32 [[SOFFSET:%.*]], i32 2, i32 3) +// CHECK-NEXT: ret void +// +void test_amdgcn_struct_ptr_buffer_load_lds(__amdgpu_buffer_rsrc_t rsrc, __local void * lds, int size, int vindex, int voffset, int soffset) { + __builtin_amdgcn_struct_ptr_buffer_load_lds(rsrc, lds, 4, vindex, voffset, soffset, 2, 3); +} diff --git a/clang/test/CodeGenOpenCL/scoped-atomic.cl b/clang/test/CodeGenOpenCL/scoped-atomic.cl new file mode 100644 index 0000000000000..ec7e936684a3a --- /dev/null +++ b/clang/test/CodeGenOpenCL/scoped-atomic.cl @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -triple spir-unknown-unknown -verify +// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -triple spir64-unknown-unknown -verify + +// expected-no-diagnostics + +int fi1a(int *i) { + int v; + __scoped_atomic_load(i, &v, __ATOMIC_RELAXED, __MEMORY_SCOPE_DEVICE); + return v; +} + +#ifdef __SPIR64__ +long fl1a(long *i) { + long v; + __scoped_atomic_load(i, &v, __ATOMIC_RELAXED, __MEMORY_SCOPE_DEVICE); + return v; +} +#endif diff --git a/clang/test/CodeGenSPIRV/Builtins/refract.c b/clang/test/CodeGenSPIRV/Builtins/refract.c new file mode 100644 index 0000000000000..f399462d68d4a --- /dev/null +++ b/clang/test/CodeGenSPIRV/Builtins/refract.c @@ -0,0 +1,74 @@ +// RUN: %clang_cc1 -O1 -triple spirv-pc-vulkan-compute %s -fnative-half-type -emit-llvm -o - | FileCheck %s + +typedef _Float16 half; +typedef half half2 __attribute__((ext_vector_type(2))); +typedef half half3 __attribute__((ext_vector_type(3))); +typedef half half4 __attribute__((ext_vector_type(4))); +typedef float float2 __attribute__((ext_vector_type(2))); +typedef float float3 __attribute__((ext_vector_type(3))); +typedef float float4 __attribute__((ext_vector_type(4))); + +// CHECK-LABEL: define spir_func half @test_refract_half( +// CHECK-SAME: half noundef [[I:%.*]], half noundef [[N:%.*]], half noundef [[ETA:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK: [[SPV_REFRACT:%.*]] = tail call half @llvm.spv.refract.f16.f16(half [[I]], half [[N]], half [[ETA]]) +// CHECK-NEXT: ret half [[SPV_REFRACT]] +// +half test_refract_half(half I, half N, half eta) { return __builtin_spirv_refract(I, N, eta); } + +// CHECK-LABEL: define spir_func <2 x half> @test_refract_half2( +// CHECK-SAME: <2 x half> noundef [[I:%.*]], <2 x half> noundef [[N:%.*]], half noundef [[ETA:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK: [[SPV_REFRACT:%.*]] = tail call <2 x half> @llvm.spv.refract.v2f16.f16(<2 x half> [[I]], <2 x half> [[N]], half [[ETA]]) +// CHECK-NEXT: ret <2 x half> [[SPV_REFRACT]] +// +half2 test_refract_half2(half2 I, half2 N, half eta) { return __builtin_spirv_refract(I, N, eta); } + +// CHECK-LABEL: define spir_func <3 x half> @test_refract_half3( +// CHECK-SAME: <3 x half> noundef [[I:%.*]], <3 x half> noundef [[N:%.*]], half noundef [[ETA:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[SPV_REFRACT:%.*]] = tail call <3 x half> @llvm.spv.refract.v3f16.f16(<3 x half> [[I]], <3 x half> [[N]], half [[ETA]]) +// CHECK-NEXT: ret <3 x half> [[SPV_REFRACT]] +// +half3 test_refract_half3(half3 I, half3 N, half eta) { return __builtin_spirv_refract(I, N, eta); } + +// CHECK-LABEL: define spir_func <4 x half> @test_refract_half4( +// CHECK-SAME: <4 x half> noundef [[I:%.*]], <4 x half> noundef [[N:%.*]], half noundef [[ETA:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[SPV_REFRACT:%.*]] = tail call <4 x half> @llvm.spv.refract.v4f16.f16(<4 x half> [[I]], <4 x half> [[N]], half [[ETA]]) +// CHECK-NEXT: ret <4 x half> [[SPV_REFRACT]] +// +half4 test_refract_half4(half4 I, half4 N, half eta) { return __builtin_spirv_refract(I, N, eta); } + + +// CHECK-LABEL: define spir_func float @test_refract_float( +// CHECK-SAME: float noundef [[I:%.*]], float noundef [[N:%.*]], float noundef [[ETA:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK: [[SPV_REFRACT:%.*]] = tail call float @llvm.spv.refract.f32.f32(float [[I]], float [[N]], float [[ETA]]) +// CHECK-NEXT: ret float [[SPV_REFRACT]] +// +float test_refract_float(float I, float N, float eta) { return __builtin_spirv_refract(I, N, eta); } + +// CHECK-LABEL: define spir_func <2 x float> @test_refract_float2( +// CHECK-SAME: <2 x float> noundef [[I:%.*]], <2 x float> noundef [[N:%.*]], float noundef [[ETA:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK: [[SPV_REFRACT:%.*]] = tail call <2 x float> @llvm.spv.refract.v2f32.f32(<2 x float> [[I]], <2 x float> [[N]], float [[ETA]]) +// CHECK-NEXT: ret <2 x float> [[SPV_REFRACT]] +// +float2 test_refract_float2(float2 I, float2 N, float eta) { return __builtin_spirv_refract(I, N, eta); } + +// CHECK-LABEL: define spir_func <3 x float> @test_refract_float3( +// CHECK-SAME: <3 x float> noundef [[I:%.*]], <3 x float> noundef [[N:%.*]], float noundef [[ETA:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[SPV_REFRACT:%.*]] = tail call <3 x float> @llvm.spv.refract.v3f32.f32(<3 x float> [[I]], <3 x float> [[N]], float [[ETA]]) +// CHECK-NEXT: ret <3 x float> [[SPV_REFRACT]] +// +float3 test_refract_float3(float3 I, float3 N, float eta) { return __builtin_spirv_refract(I, N, eta); } + +// CHECK-LABEL: define spir_func <4 x float> @test_refract_float4( +// CHECK-SAME: <4 x float> noundef [[I:%.*]], <4 x float> noundef [[N:%.*]], float noundef [[ETA:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[SPV_REFRACT:%.*]] = tail call <4 x float> @llvm.spv.refract.v4f32.f32(<4 x float> [[I]], <4 x float> [[N]], float [[ETA]]) +// CHECK-NEXT: ret <4 x float> [[SPV_REFRACT]] +// +float4 test_refract_float4(float4 I, float4 N, float eta) { return __builtin_spirv_refract(I, N, eta); } diff --git a/clang/test/DebugInfo/KeyInstructions/asm.c b/clang/test/DebugInfo/KeyInstructions/asm.c new file mode 100644 index 0000000000000..2b3301660f7ba --- /dev/null +++ b/clang/test/DebugInfo/KeyInstructions/asm.c @@ -0,0 +1,59 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -triple aarch64 -target-feature +ls64 -O0 -emit-llvm -x c %s -o - -gkey-instructions -debug-info-kind=line-tables-only -gno-column-info | FileCheck %s +// Partially copied from clang/test/CodeGen/AArch64/ls64-inline-asm.c + +// Check the inline asm call and result store are Key and distinct atoms. + +struct foo { unsigned long long x[8]; }; +// CHECK-LABEL: define dso_local void @load( +// CHECK-SAME: ptr noundef [[OUTPUT:%.*]], ptr noundef [[ADDR:%.*]]) #[[ATTR0:[0-9]+]] !dbg [[DBG5:![0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[OUTPUT_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[ADDR_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[OUTPUT]], ptr [[OUTPUT_ADDR]], align 8 +// CHECK-NEXT: store ptr [[ADDR]], ptr [[ADDR_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 8, !dbg [[DBG9:![0-9]+]] +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ADDR_ADDR]], align 8, !dbg [[DBG9]] +// CHECK-NEXT: [[TMP2:%.*]] = call i512 asm sideeffect "ld64b $0,[$1]", "=r,r,~{memory}"(ptr [[TMP1]]) #[[ATTR1:[0-9]+]], !dbg [[DBG10:![0-9]+]], !srcloc [[META11:![0-9]+]] +// CHECK-NEXT: store i512 [[TMP2]], ptr [[TMP0]], align 8, !dbg [[DBG12:![0-9]+]] +// CHECK-NEXT: ret void, !dbg [[DBG13:![0-9]+]] +// +void load(struct foo *output, void *addr) { + __asm__ volatile ("ld64b %0,[%1]" : "=r" (*output) : "r" (addr) : "memory"); +} + +// CHECK-LABEL: define dso_local void @load2( +// CHECK-SAME: ptr noundef [[OUTPUT:%.*]], ptr noundef [[ADDR:%.*]]) #[[ATTR0]] !dbg [[DBG14:![0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[OUTPUT_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[ADDR_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[OUTPUT]], ptr [[OUTPUT_ADDR]], align 8 +// CHECK-NEXT: store ptr [[ADDR]], ptr [[ADDR_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 8, !dbg [[DBG15:![0-9]+]] +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ADDR_ADDR]], align 8, !dbg [[DBG15]] +// CHECK-NEXT: [[TMP2:%.*]] = call i32 asm sideeffect "ld64b $0,[$1]", "=r,r,~{memory}"(ptr [[TMP1]]) #[[ATTR1]], !dbg [[DBG16:![0-9]+]], !srcloc [[META17:![0-9]+]] +// CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP0]], align 4, !dbg [[DBG18:![0-9]+]] +// CHECK-NEXT: ret void, !dbg [[DBG19:![0-9]+]] +// +void load2(int *output, void *addr) { + __asm__ volatile ("ld64b %0,[%1]" : "=r" (*output) : "r" (addr) : "memory"); +} +//. +// CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C11, file: [[META1:![0-9]+]], producer: "{{.*}}clang version {{.*}}", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, splitDebugInlining: false, nameTableKind: None) +// CHECK: [[META1]] = !DIFile(filename: "{{.*}}", directory: {{.*}}) +// CHECK: [[DBG5]] = distinct !DISubprogram(name: "load", scope: [[META6:![0-9]+]], file: [[META6]], line: 21, type: [[META7:![0-9]+]], scopeLine: 21, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], keyInstructions: true) +// CHECK: [[META6]] = !DIFile(filename: "{{.*}}asm.c", directory: {{.*}}) +// CHECK: [[META7]] = !DISubroutineType(types: [[META8:![0-9]+]]) +// CHECK: [[META8]] = !{} +// CHECK: [[DBG9]] = !DILocation(line: 22, scope: [[DBG5]]) +// CHECK: [[DBG10]] = !DILocation(line: 22, scope: [[DBG5]], atomGroup: 1, atomRank: 1) +// CHECK: [[META11]] = !{i64 1458} +// CHECK: [[DBG12]] = !DILocation(line: 22, scope: [[DBG5]], atomGroup: 2, atomRank: 1) +// CHECK: [[DBG13]] = !DILocation(line: 23, scope: [[DBG5]], atomGroup: 3, atomRank: 1) +// CHECK: [[DBG14]] = distinct !DISubprogram(name: "load2", scope: [[META6]], file: [[META6]], line: 38, type: [[META7]], scopeLine: 38, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], keyInstructions: true) +// CHECK: [[DBG15]] = !DILocation(line: 39, scope: [[DBG14]]) +// CHECK: [[DBG16]] = !DILocation(line: 39, scope: [[DBG14]], atomGroup: 1, atomRank: 1) +// CHECK: [[META17]] = !{i64 2501} +// CHECK: [[DBG18]] = !DILocation(line: 39, scope: [[DBG14]], atomGroup: 2, atomRank: 1) +// CHECK: [[DBG19]] = !DILocation(line: 40, scope: [[DBG14]], atomGroup: 3, atomRank: 1) +//. diff --git a/clang/test/DebugInfo/KeyInstructions/goto.c b/clang/test/DebugInfo/KeyInstructions/goto.c new file mode 100644 index 0000000000000..ead92e600ca5b --- /dev/null +++ b/clang/test/DebugInfo/KeyInstructions/goto.c @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -x c++ -std=c++17 %s -debug-info-kind=line-tables-only -emit-llvm -o - -gno-column-info \ +// RUN: | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - -gno-column-info \ +// RUN: | FileCheck %s + +// Check the goto branches get Key Instructions metadata. +void ext(); +void test_goto(void) { +// CHECK: br label %dst1, !dbg [[G1R1:!.*]] + goto dst1; +dst1: + ext(); + + void *ptr = &&dst2; +// CHECK: br label %indirectgoto, !dbg [[G3R1:!.*]] + goto *ptr; +dst2: + ext(); + +// CHECK: br label %dst3, !dbg [[G4R1:!.*]] + goto *&&dst3; +dst3: + ext(); + + return; +} + +// CHECK: [[G1R1]] = !DILocation(line: 10, scope: ![[#]], atomGroup: 1, atomRank: 1) +// CHECK: [[G3R1]] = !DILocation(line: 16, scope: ![[#]], atomGroup: 3, atomRank: 1) +// CHECK: [[G4R1]] = !DILocation(line: 21, scope: ![[#]], atomGroup: 4, atomRank: 1) diff --git a/clang/test/Driver/amdgpu-hip-system-arch.c b/clang/test/Driver/amdgpu-hip-system-arch.c index 9c27bc09fb36c..12e298a8636b1 100644 --- a/clang/test/Driver/amdgpu-hip-system-arch.c +++ b/clang/test/Driver/amdgpu-hip-system-arch.c @@ -14,14 +14,14 @@ // RUN: | FileCheck %s --check-prefix=NO-OUTPUT-ERROR // RUN: not %clang -### --target=x86_64-unknown-linux-gnu -nogpulib --offload-new-driver --offload-arch=native --amdgpu-arch-tool=%t/amdgpu_arch_fail -x hip %s 2>&1 \ // RUN: | FileCheck %s --check-prefix=NO-OUTPUT-ERROR -// NO-OUTPUT-ERROR: error: cannot determine amdgcn architecture{{.*}}; consider passing it via '--offload-arch' +// NO-OUTPUT-ERROR: error: cannot determine hip architecture{{.*}}; consider passing it via '--offload-arch' // case when amdgpu-arch does not return anything with successful execution // RUN: not %clang -### --target=x86_64-unknown-linux-gnu -nogpulib --offload-arch=native --amdgpu-arch-tool=%t/amdgpu_arch_empty -x hip %s 2>&1 \ // RUN: | FileCheck %s --check-prefix=EMPTY-OUTPUT // RUN: not %clang -### --target=x86_64-unknown-linux-gnu -nogpulib --offload-new-driver --offload-arch=native --amdgpu-arch-tool=%t/amdgpu_arch_empty -x hip %s 2>&1 \ // RUN: | FileCheck %s --check-prefix=EMPTY-OUTPUT -// EMPTY-OUTPUT: error: cannot determine amdgcn architecture: No AMD GPU detected in the system; consider passing it via '--offload-arch' +// EMPTY-OUTPUT: error: cannot determine hip architecture: No GPU detected in the system; consider passing it via '--offload-arch' // case when amdgpu-arch returns a gfx906 GPU. // RUN: %clang -### --target=x86_64-unknown-linux-gnu -nogpuinc -nogpulib --offload-arch=native --amdgpu-arch-tool=%t/amdgpu_arch_gfx906 -x hip %s 2>&1 \ @@ -36,4 +36,4 @@ // RUN: --offload-arch=native --amdgpu-arch-tool=%t/amdgpu_arch_gfx906 \ // RUN: -x hip %s 2>&1 | \ // RUN: FileCheck %s --check-prefix=BAD-TIMEOUT -// BAD-TIMEOUT: clang: error: cannot determine amdgcn architecture: CLANG_TOOLCHAIN_PROGRAM_TIMEOUT expected an integer, got 'foo'; consider passing it via '--offload-arch'; environment variable CLANG_TOOLCHAIN_PROGRAM_TIMEOUT specifies the tool timeout (integer secs, <=0 is infinite) +// BAD-TIMEOUT: clang: error: cannot determine hip architecture: CLANG_TOOLCHAIN_PROGRAM_TIMEOUT expected an integer, got 'foo'; consider passing it via '--offload-arch'; environment variable CLANG_TOOLCHAIN_PROGRAM_TIMEOUT specifies the tool timeout (integer secs, <=0 is infinite) diff --git a/clang/test/Driver/baremetal.cpp b/clang/test/Driver/baremetal.cpp index 4dc320191317e..adb59e1debd4e 100644 --- a/clang/test/Driver/baremetal.cpp +++ b/clang/test/Driver/baremetal.cpp @@ -257,7 +257,7 @@ // CHECK-RV64-SAME:"{{.*}}.o" // CHECK-RV64-SAME: "{{[^"]*}}libclang_rt.builtins.a" // CHECK-RV64-SAME: "-lc" -// CHECK-RV64-SAME: "-X" "-o" "{{.*}}.tmp.out" +// CHECK-RV64-SAME: "-o" "{{.*}}.tmp.out" // RUN: %clangxx %s -### --target=riscv64-unknown-elf 2>&1 \ // RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf \ @@ -271,7 +271,7 @@ // CHECK-RV64-DEFAULTCXX-SAME: "-lc++" "-lm" // CHECK-RV64-DEFAULTCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" // CHECK-RV64-DEFAULTCXX-SAME: "-lc" -// CHECK-RV64-DEFAULTCXX-SAME: "-X" "-o" "a.out" +// CHECK-RV64-DEFAULTCXX-SAME: "-o" "a.out" // RUN: %clangxx %s -### --target=riscv64-unknown-elf 2>&1 \ // RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf \ @@ -288,7 +288,7 @@ // CHECK-RV64-LIBCXX-SAME: "-lc++" "-lm" // CHECK-RV64-LIBCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" // CHECK-RV64-LIBCXX-SAME: "-lc" -// CHECK-RV64-LIBCXX-SAME: "-X" "-o" "a.out" +// CHECK-RV64-LIBCXX-SAME: "-o" "a.out" // RUN: %clangxx %s -### 2>&1 --target=riscv64-unknown-elf \ // RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf \ @@ -305,7 +305,7 @@ // CHECK-RV64-LIBSTDCXX-SAME: "-lstdc++" "-lm" // CHECK-RV64-LIBSTDCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" // CHECK-RV64-LIBSTDCXX-SAME: "-lc" -// CHECK-RV64-LIBSTDCXX-SAME: "-X" "-o" "a.out" +// CHECK-RV64-LIBSTDCXX-SAME: "-o" "a.out" // RUN: %clang %s -### 2>&1 --target=riscv32-unknown-elf \ // RUN: -L some/directory/user/asked/for \ @@ -325,7 +325,7 @@ // CHECK-RV32-SAME: "{{.*}}.o" // CHECK-RV32-SAME: "{{[^"]*}}libclang_rt.builtins.a" // CHECK-RV32-SAME: "-lc" -// CHECK-RV32-SAME: "-X" "-o" "a.out" +// CHECK-RV32-SAME: "-o" "a.out" // RUN: %clangxx %s -### 2>&1 --target=riscv32-unknown-elf \ // RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf \ @@ -339,7 +339,7 @@ // CHECK-RV32-DEFAULTCXX-SAME: "-lc++" "-lm" // CHECK-RV32-DEFAULTCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" // CHECK-RV32-DEFAULTCXX-SAME: "-lc" -// CHECK-RV32-DEFAULTCXX-SAME: "-X" "-o" "a.out" +// CHECK-RV32-DEFAULTCXX-SAME: "-o" "a.out" // RUN: %clangxx %s -### 2>&1 --target=riscv32-unknown-elf \ // RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf \ @@ -355,7 +355,7 @@ // CHECK-RV32-LIBCXX-SAME: "{{.*}}.o" // CHECK-RV32-LIBCXX-SAME: "-lc++" "-lm" // CHECK-RV32-LIBCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" -// CHECK-RV32-LIBCXX-SAME: "-X" "-o" "a.out" +// CHECK-RV32-LIBCXX-SAME: "-o" "a.out" // RUN: %clangxx %s -### 2>&1 --target=riscv32-unknown-elf \ // RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf \ @@ -372,7 +372,7 @@ // CHECK-RV32-LIBSTDCXX-SAME: "-lstdc++" "-lm" // CHECK-RV32-LIBSTDCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" // CHECK-RV32-LIBSTDCXX-SAME: "-lc" -// CHECK-RV32-LIBSTDCXX-SAME: "-X" "-o" "a.out" +// CHECK-RV32-LIBSTDCXX-SAME: "-o" "a.out" // RUN: %clang %s -### 2>&1 --target=riscv64-unknown-elf \ // RUN: -nostdlibinc -nobuiltininc \ diff --git a/clang/test/Driver/cuda-phases.cu b/clang/test/Driver/cuda-phases.cu index 8b91a1d5a7fcf..220a320e32705 100644 --- a/clang/test/Driver/cuda-phases.cu +++ b/clang/test/Driver/cuda-phases.cu @@ -324,8 +324,8 @@ // RUN: -ccc-print-phases --offload-arch=sm_999 -fgpu-rdc -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=INVALID-ARCH %s // INVALID-ARCH: error: unsupported CUDA gpu architecture: sm_999 -// INVALID-ARCH-NEXT: 0: input, "[[INPUT:.+]]", cuda, (host-cuda) -// INVALID-ARCH-NEXT: 1: preprocessor, {0}, cuda-cpp-output, (host-cuda) -// INVALID-ARCH-NEXT: 2: compiler, {1}, ir, (host-cuda) -// INVALID-ARCH-NEXT: 3: backend, {2}, assembler, (host-cuda) -// INVALID-ARCH-NEXT: 4: assembler, {3}, object, (host-cuda) +// INVALID-ARCH: 0: input, "[[INPUT:.+]]", cuda +// INVALID-ARCH-NEXT: 1: preprocessor, {0}, cuda-cpp-output +// INVALID-ARCH-NEXT: 2: compiler, {1}, ir +// INVALID-ARCH-NEXT: 3: backend, {2}, assembler +// INVALID-ARCH-NEXT: 4: assembler, {3}, object diff --git a/clang/test/Driver/frame-pointer-elim.c b/clang/test/Driver/frame-pointer-elim.c index f00940bd7613d..6e21671f43775 100644 --- a/clang/test/Driver/frame-pointer-elim.c +++ b/clang/test/Driver/frame-pointer-elim.c @@ -162,7 +162,7 @@ // RUN: FileCheck --check-prefix=KEEP-ALL %s // RUN: %clang -### --target=riscv64-linux-android -O1 -S %s 2>&1 | \ // RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s -// RUN: not %clang -### --target=riscv64-linux-android -mbig-endian -O1 -S %s 2>&1 | \ +// RUN: %clang -### --target=riscv64-linux-android -mbig-endian -O1 -S %s 2>&1 | \ // RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s // On ARM backend bare metal targets, frame pointer is omitted diff --git a/clang/test/Driver/hip-inputs.hip b/clang/test/Driver/hip-inputs.hip index 2d4cc3103c5ec..a8e25ad8ed198 100644 --- a/clang/test/Driver/hip-inputs.hip +++ b/clang/test/Driver/hip-inputs.hip @@ -15,5 +15,5 @@ // RUN: --hip-link %S/Inputs/hip_multiple_inputs/a.cu 2>&1 \ // RUN: | FileCheck -check-prefix=MIX %s -// CHECK-NOT: error: mixed CUDA and HIP compilation is not supported -// MIX: error: mixed CUDA and HIP compilation is not supported +// CHECK-NOT: error: mixed CUDA and HIP offloading compilation is not supported +// MIX: error: mixed CUDA and HIP offloading compilation is not supported diff --git a/clang/test/Driver/hip-invalid-target-id.hip b/clang/test/Driver/hip-invalid-target-id.hip index 555043facb2a3..ad942e476617e 100644 --- a/clang/test/Driver/hip-invalid-target-id.hip +++ b/clang/test/Driver/hip-invalid-target-id.hip @@ -4,7 +4,7 @@ // RUN: --rocm-path=%S/Inputs/rocm \ // RUN: %s 2>&1 | FileCheck -check-prefix=NOPLUS %s -// NOPLUS: error: invalid target ID 'gfx908xnack' +// NOPLUS: error: unsupported HIP gpu architecture: gfx908xnack // RUN: not %clang -### --target=x86_64-linux-gnu \ // RUN: -x hip --offload-arch=gfx900 \ @@ -22,7 +22,7 @@ // RUN: --rocm-path=%S/Inputs/rocm \ // RUN: %s 2>&1 | FileCheck -check-prefix=UNK %s -// UNK: error: invalid target ID 'gfx908:unknown+' +// UNK: error: unsupported HIP gpu architecture: gfx900+xnack // RUN: not %clang -### --target=x86_64-linux-gnu \ // RUN: -x hip --offload-arch=gfx908 \ @@ -31,7 +31,7 @@ // RUN: --rocm-path=%S/Inputs/rocm \ // RUN: %s 2>&1 | FileCheck -check-prefix=MIXED %s -// MIXED: error: invalid target ID 'gfx908:sramecc+:unknown+' +// MIXED: error: unsupported HIP gpu architecture: gfx900+xnack // RUN: not %clang -### --target=x86_64-linux-gnu \ // RUN: -x hip --offload-arch=gfx908 \ @@ -55,7 +55,7 @@ // RUN: --rocm-path=%S/Inputs/rocm \ // RUN: %s 2>&1 | FileCheck -check-prefix=NOCOLON %s -// NOCOLON: error: invalid target ID 'gfx900+xnack' +// NOCOLON: error: unsupported HIP gpu architecture: gfx900+xnack // RUN: not %clang -### --target=x86_64-linux-gnu \ // RUN: -x hip --offload-arch=gfx908 \ diff --git a/clang/test/Driver/hip-options.hip b/clang/test/Driver/hip-options.hip index 4fb5571b838fb..ba23bc2d59b56 100644 --- a/clang/test/Driver/hip-options.hip +++ b/clang/test/Driver/hip-options.hip @@ -115,11 +115,6 @@ // OMP-NOT: "-cc1"{{.*}} "-triple" "amdgcn-amd-amdhsa" {{.*}} "-fopenmp" // OMP: "-cc1"{{.*}} "-triple" "x86_64-unknown-linux-gnu" {{.*}} "-fopenmp" -// RUN: not %clang --target=x86_64-unknown-linux-gnu -nogpuinc -nogpulib \ -// RUN: --offload-arch=gfx906 -fopenmp=libomp -fopenmp-targets=amdgcn %s 2>&1 \ -// RUN: | FileCheck -check-prefix=OMPTGT %s -// OMPTGT: unsupported option '--offload-targets=' for language mode 'HIP' - // Check -Xoffload-linker option is passed to lld. // RUN: %clang -### --target=x86_64-unknown-linux-gnu -nogpuinc -nogpulib \ diff --git a/clang/test/Driver/invalid-offload-options.cpp b/clang/test/Driver/invalid-offload-options.cpp index 48d5310538a3c..6048a3ca82e77 100644 --- a/clang/test/Driver/invalid-offload-options.cpp +++ b/clang/test/Driver/invalid-offload-options.cpp @@ -1,29 +1,7 @@ // UNSUPPORTED: system-windows -// RUN: not %clang -### -x hip --target=x86_64-linux-gnu --offload= \ -// RUN: --hip-path=%S/Inputs/hipspv -nogpuinc -nogpulib %s \ -// RUN: 2>&1 | FileCheck --check-prefix=INVALID-TARGET %s // RUN: not %clang -### -x hip --target=x86_64-linux-gnu --offload=foo \ // RUN: --hip-path=%S/Inputs/hipspv -nogpuinc -nogpulib %s \ // RUN: 2>&1 | FileCheck --check-prefix=INVALID-TARGET %s // INVALID-TARGET: error: invalid or unsupported offload target: '{{.*}}' - -// In the future we should be able to specify multiple targets for HIP -// compilation but currently it is not supported. -// -// RUN: not %clang -### -x hip --target=x86_64-linux-gnu --offload=foo,bar \ -// RUN: --hip-path=%S/Inputs/hipspv -nogpuinc -nogpulib %s \ -// RUN: 2>&1 | FileCheck --check-prefix=TOO-MANY-TARGETS %s -// RUN: not %clang -### -x hip --target=x86_64-linux-gnu \ -// RUN: --offload=foo --offload=bar \ -// RUN: --hip-path=%S/Inputs/hipspv -nogpuinc -nogpulib %s \ -// RUN: 2>&1 | FileCheck --check-prefix=TOO-MANY-TARGETS %s - -// TOO-MANY-TARGETS: error: only one offload target is supported - -// RUN: not %clang -### -x hip --target=x86_64-linux-gnu -nogpuinc -nogpulib \ -// RUN: --offload=amdgcn-amd-amdhsa --offload-arch=gfx900 %s \ -// RUN: 2>&1 | FileCheck --check-prefix=OFFLOAD-ARCH-MIX %s - -// OFFLOAD-ARCH-MIX: error: option '--offload-arch' cannot be specified with '--offload' diff --git a/clang/test/Driver/module-fgen-reduced-bmi.cppm b/clang/test/Driver/module-fgen-reduced-bmi.cppm index 9bdd4c9f6682f..4b893ffbfaae8 100644 --- a/clang/test/Driver/module-fgen-reduced-bmi.cppm +++ b/clang/test/Driver/module-fgen-reduced-bmi.cppm @@ -64,7 +64,8 @@ // RUN: -Wno-missing-reduced-bmi -### 2>&1 | FileCheck Hello.cppm -check-prefix=NO_WARN // // RUN: %clang -std=c++20 Hello.cppm --precompile -o Hello.pcm \ -// RUN: -Wno-missing-reduced-bmi -### 2>&1 | FileCheck Hello.cppm -check-prefix=NO_WARN +// RUN: -fno-modules-reduced-bmi -Wno-missing-reduced-bmi -### 2>&1 | \ +// RUN: FileCheck Hello.cppm -check-prefix=NO_WARN //--- Hello.cppm export module Hello; diff --git a/clang/test/Driver/module-output.cppm b/clang/test/Driver/module-output.cppm index 7cf0771f3d6ef..197f1d85b0f9c 100644 --- a/clang/test/Driver/module-output.cppm +++ b/clang/test/Driver/module-output.cppm @@ -13,28 +13,29 @@ // Tests that the .pcm file will be generated in the same directory with the specified // output and the name of the .pcm file should be the same with the input file. // RUN: %clang -std=c++20 %t/Hello.cppm -fmodule-output -c -o %t/output/Hello.o \ -// RUN: -### 2>&1 | FileCheck %t/Hello.cppm +// RUN: -fno-modules-reduced-bmi -### 2>&1 | FileCheck %t/Hello.cppm // // Tests that the output file will be generated in the input directory if the output // file is not the corresponding object file. // RUN: %clang -std=c++20 %t/Hello.cppm %t/AnotherModule.cppm -fmodule-output -o \ -// RUN: %t/output/a.out -### 2>&1 | FileCheck %t/AnotherModule.cppm +// RUN: %t/output/a.out -fno-modules-reduced-bmi -### 2>&1 | FileCheck %t/AnotherModule.cppm // // Tests that clang will reject the command line if it specifies -fmodule-output with // multiple archs. // RUN: not %clang %t/Hello.cppm -fmodule-output -arch i386 -arch x86_64 -### \ -// RUN: --target=x86_64-apple-darwin 2>&1 | FileCheck %t/Hello.cppm -check-prefix=MULTIPLE-ARCH +// RUN: -fno-modules-reduced-bmi --target=x86_64-apple-darwin 2>&1 | FileCheck %t/Hello.cppm \ +// RUN: -check-prefix=MULTIPLE-ARCH // Tests that the .pcm file will be generated in the same path with the specified one // in the comamnd line. // RUN: %clang -std=c++20 %t/Hello.cppm -fmodule-output=%t/pcm/Hello.pcm -o %t/Hello.o \ -// RUN: -c -### 2>&1 | FileCheck %t/Hello.cppm --check-prefix=CHECK-SPECIFIED +// RUN: -fno-modules-reduced-bmi -c -### 2>&1 | FileCheck %t/Hello.cppm --check-prefix=CHECK-SPECIFIED // // RUN: %clang -std=c++20 %t/Hello.cppm -fmodule-output=%t/Hello.pcm -fmodule-output -c -fsyntax-only \ -// RUN: -### 2>&1 | FileCheck %t/Hello.cppm --check-prefix=CHECK-NOT-USED +// RUN: -fno-modules-reduced-bmi -### 2>&1 | FileCheck %t/Hello.cppm --check-prefix=CHECK-NOT-USED // Test that we can emit a warning if the type of the input file is not a module interface unit. -// RUN: %clang -std=c++20 %t/a.cpp -fmodule-output -c -o %t/a.o -### 2>&1 | FileCheck %t/a.cpp +// RUN: %clang -std=c++20 %t/a.cpp -fmodule-output -fno-modules-reduced-bmi -c -o %t/a.o -### 2>&1 | FileCheck %t/a.cpp //--- Hello.cppm export module Hello; diff --git a/clang/test/Driver/modules.cpp b/clang/test/Driver/modules.cpp index 088a73230f81e..edbe8d8e92c85 100644 --- a/clang/test/Driver/modules.cpp +++ b/clang/test/Driver/modules.cpp @@ -34,7 +34,7 @@ // Check combining precompile and compile steps works. // -// RUN: %clang -std=c++2a -x c++-module %t/foo.cpp -S -o %t/foo2.pcm.o -v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE --check-prefix=CHECK-COMPILE +// RUN: %clang -std=c++2a -x c++-module -fno-modules-reduced-bmi %t/foo.cpp -S -o %t/foo2.pcm.o -v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE --check-prefix=CHECK-COMPILE // Check that .cppm is treated as a module implicitly. // diff --git a/clang/test/Driver/nvptx-cuda-system-arch.c b/clang/test/Driver/nvptx-cuda-system-arch.c index c54eeac73f73b..2d4eca8c43bc3 100644 --- a/clang/test/Driver/nvptx-cuda-system-arch.c +++ b/clang/test/Driver/nvptx-cuda-system-arch.c @@ -16,14 +16,14 @@ // RUN: | FileCheck %s --check-prefix=NO-OUTPUT-ERROR // RUN: not %clang -### --target=x86_64-unknown-linux-gnu -nogpulib --offload-new-driver --offload-arch=native --nvptx-arch-tool=%t/nvptx_arch_fail -x cuda %s 2>&1 \ // RUN: | FileCheck %s --check-prefix=NO-OUTPUT-ERROR -// NO-OUTPUT-ERROR: error: cannot determine nvptx64 architecture{{.*}}; consider passing it via '--offload-arch' +// NO-OUTPUT-ERROR: error: cannot determine cuda architecture{{.*}}; consider passing it via '--offload-arch' // case when nvptx-arch does not return anything with successful execution // RUN: not %clang -### --target=x86_64-unknown-linux-gnu -nogpulib --offload-arch=native --nvptx-arch-tool=%t/nvptx_arch_empty -x cuda %s 2>&1 \ // RUN: | FileCheck %s --check-prefix=EMPTY-OUTPUT // RUN: not %clang -### --target=x86_64-unknown-linux-gnu -nogpulib --offload-new-driver --offload-arch=native --nvptx-arch-tool=%t/nvptx_arch_empty -x cuda %s 2>&1 \ // RUN: | FileCheck %s --check-prefix=EMPTY-OUTPUT -// EMPTY-OUTPUT: error: cannot determine nvptx64 architecture: No NVIDIA GPU detected in the system; consider passing it via '--offload-arch' +// EMPTY-OUTPUT: error: cannot determine cuda architecture: No GPU detected in the system; consider passing it via '--offload-arch' // case when nvptx-arch does not return anything with successful execution // RUN: %clang -### --target=x86_64-unknown-linux-gnu -nogpulib --offload-arch=native --nvptx-arch-tool=%t/nvptx_arch_sm_70 -x cuda --cuda-path=%S/Inputs/CUDA_102/usr/local/cuda %s 2>&1 \ @@ -49,4 +49,4 @@ // RUN: --offload-arch=native --nvptx-arch-tool=%t/nvptx_arch_sm_70 \ // RUN: --cuda-path=%S/Inputs/CUDA_102/usr/local/cuda -x cuda %s 2>&1 | \ // RUN: FileCheck %s --check-prefix=BAD-TIMEOUT -// BAD-TIMEOUT: clang: error: cannot determine nvptx64 architecture: CLANG_TOOLCHAIN_PROGRAM_TIMEOUT expected an integer, got 'foo'; consider passing it via '--offload-arch'; environment variable CLANG_TOOLCHAIN_PROGRAM_TIMEOUT specifies the tool timeout (integer secs, <=0 is infinite) +// BAD-TIMEOUT: clang: error: cannot determine cuda architecture: CLANG_TOOLCHAIN_PROGRAM_TIMEOUT expected an integer, got 'foo'; consider passing it via '--offload-arch'; environment variable CLANG_TOOLCHAIN_PROGRAM_TIMEOUT specifies the tool timeout (integer secs, <=0 is infinite) diff --git a/clang/test/Driver/offload-target.c b/clang/test/Driver/offload-target.c new file mode 100644 index 0000000000000..123ecd3eb830e --- /dev/null +++ b/clang/test/Driver/offload-target.c @@ -0,0 +1,22 @@ +// RUN: %clang -### -fsycl --offload-targets=spirv64 -nogpuinc %s -ccc-print-bindings 2>&1 \ +// RUN: | FileCheck %s -check-prefix=SYCL +// SYCL: "spirv64" - "clang", inputs: ["[[INPUT:.+]]"], output: "[[SYCL_BC:.+]]" + +// RUN: %clang -### --offload-targets=amdgcn-amd-amdhsa -nogpulib -nogpuinc -x hip %s -ccc-print-bindings 2>&1 \ +// RUN: | FileCheck %s -check-prefix=HIP +// HIP: "amdgcn-amd-amdhsa" - "clang", inputs: ["[[INPUT:.+]]"], output: "[[AMD_OBJ:.+]]" + +// RUN: %clang -### --offload-targets=nvptx64-nvidia-cuda -nogpulib -nogpuinc -x cuda %s -ccc-print-bindings 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CUDA +// CUDA: "nvptx64-nvidia-cuda" - "clang", inputs: ["[[INPUT:.+]]"], output: "[[NV_OBJ:.+]]" + +// RUN: %clang -### --offload-targets=amdgcn-amd-amdhsa,nvptx64-nvidia-cuda -fopenmp \ +// RUN: -Xarch_amdgcn --offload-arch=gfx90a -Xarch_nvptx64 --offload-arch=sm_89 \ +// RUN: -nogpulib -nogpuinc %s -ccc-print-bindings 2>&1 \ +// RUN: | FileCheck %s -check-prefix=OPENMP +// OPENMP: "amdgcn-amd-amdhsa" - "clang", inputs: ["[[INPUT:.+]]"], output: "[[AMD_OBJ:.+]]" +// OPENMP: "nvptx64-nvidia-cuda" - "clang", inputs: ["[[INPUT]]"], output: "[[NV_OBJ:.+]]" + +// RUN: %clang -### --offload-targets=spirv64-amd-amdhsa -nogpulib -nogpuinc -x hip %s -ccc-print-bindings 2>&1 \ +// RUN: | FileCheck %s -check-prefix=HIPSPIRV +// HIPSPIRV: "spirv64-amd-amdhsa" - "clang", inputs: ["[[INPUT:.+]]"], output: "[[AMD_OBJ:.+]]" diff --git a/clang/test/Driver/openacc.c b/clang/test/Driver/openacc.c index c7f1d2545bd03..f46e2a32bcab2 100644 --- a/clang/test/Driver/openacc.c +++ b/clang/test/Driver/openacc.c @@ -1,14 +1,2 @@ // RUN: %clang -S -### -fopenacc %s 2>&1 | FileCheck %s --check-prefix=CHECK-DRIVER // CHECK-DRIVER: "-cc1" {{.*}} "-fopenacc" - -// RUN: %clang -S -### -fopenacc -fexperimental-openacc-macro-override=202211 %s 2>&1 | FileCheck %s --check-prefix=CHECK-MACRO-OVERRIDE -// RUN: %clang -S -### -fopenacc -fexperimental-openacc-macro-override 202211 %s 2>&1 | FileCheck %s --check-prefix=CHECK-MACRO-OVERRIDE -// CHECK-MACRO-OVERRIDE: "-cc1"{{.*}} "-fexperimental-openacc-macro-override" "202211" - -// RUN: not %clang -S -fopenacc -fexperimental-openacc-macro-override=202211L %s 2>&1 | FileCheck %s --check-prefix=INVALID -// RUN: not %clang -S -fopenacc -fexperimental-openacc-macro-override 202211L %s 2>&1 | FileCheck %s --check-prefix=INVALID -// RUN: not %clang -S -fopenacc -fexperimental-openacc-macro-override=L202211 %s 2>&1 | FileCheck %s --check-prefix=INVALID -// RUN: not %clang -S -fopenacc -fexperimental-openacc-macro-override L202211 %s 2>&1 | FileCheck %s --check-prefix=INVALID -// RUN: not %clang -S -fopenacc -fexperimental-openacc-macro-override=2022L11 %s 2>&1 | FileCheck %s --check-prefix=INVALID -// RUN: not %clang -S -fopenacc -fexperimental-openacc-macro-override 2022L11 %s 2>&1 | FileCheck %s --check-prefix=INVALID -// INVALID: error: the clang compiler does not support diff --git a/clang/test/Driver/openbsd.c b/clang/test/Driver/openbsd.c index 6639e9d2d9d67..1f12cfca9488b 100644 --- a/clang/test/Driver/openbsd.c +++ b/clang/test/Driver/openbsd.c @@ -127,9 +127,12 @@ // UNWIND-TABLES: "-funwind-tables=2" // NO-UNWIND-TABLES-NOT: "-funwind-tables=2" -// Check that the -X and --no-relax flags are passed to the linker on riscv64 +// Check that the -X and --no-relax flags are passed to the linker +// RUN: %clang --target=loongarch64-unknown-openbsd -mno-relax -### %s 2>&1 \ +// RUN: | FileCheck --check-prefix=LA64-FLAGS %s // RUN: %clang --target=riscv64-unknown-openbsd -mno-relax -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=RISCV64-FLAGS %s +// LA64-FLAGS: "-X" "--no-relax" // RISCV64-FLAGS: "-X" "--no-relax" // Check passing LTO flags to the linker diff --git a/clang/test/Driver/openmp-offload.c b/clang/test/Driver/openmp-offload.c index 162ff20a9745a..64d45f9479fb6 100644 --- a/clang/test/Driver/openmp-offload.c +++ b/clang/test/Driver/openmp-offload.c @@ -7,7 +7,7 @@ /// Check whether an invalid OpenMP target is specified: // RUN: not %clang -### -fopenmp=libomp -fopenmp-targets=aaa-bbb-ccc-ddd %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-INVALID-TARGET %s -// CHK-INVALID-TARGET: error: OpenMP target is invalid: 'aaa-bbb-ccc-ddd' +// CHK-INVALID-TARGET: error: invalid or unsupported offload target: 'aaa-bbb-ccc-ddd' /// ########################################################################### @@ -18,15 +18,6 @@ /// ########################################################################### -/// Check error for no -fopenmp option -// RUN: not %clang -### -fopenmp-targets=powerpc64le-ibm-linux-gnu %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHK-NO-FOPENMP %s -// RUN: not %clang -### -fopenmp=libgomp -fopenmp-targets=powerpc64le-ibm-linux-gnu %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHK-NO-FOPENMP %s -// CHK-NO-FOPENMP: error: '-fopenmp-targets' must be used in conjunction with a '-fopenmp' option compatible with offloading; e.g., '-fopenmp=libomp' or '-fopenmp=libiomp5' - -/// ########################################################################### - /// Check warning for duplicate offloading targets. // RUN: %clang -### -ccc-print-phases -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu,powerpc64le-ibm-linux-gnu %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-DUPLICATES %s diff --git a/clang/test/Driver/openmp-system-arch.c b/clang/test/Driver/openmp-system-arch.c index b18ecf3ec474b..167b07a23f512 100644 --- a/clang/test/Driver/openmp-system-arch.c +++ b/clang/test/Driver/openmp-system-arch.c @@ -24,13 +24,7 @@ // RUN: not %clang -### --target=x86_64-unknown-linux-gnu -nogpulib -fopenmp=libomp --offload-arch=native \ // RUN: --nvptx-arch-tool=%t/nvptx_arch_empty --amdgpu-arch-tool=%t/amdgpu_arch_empty %s 2>&1 \ // RUN: | FileCheck %s --check-prefix=NO-OUTPUT-ERROR -// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -nogpulib -fopenmp=libomp --offload-arch= \ -// RUN: --nvptx-arch-tool=%t/nvptx_arch_fail --amdgpu-arch-tool=%t/amdgpu_arch_fail %s 2>&1 \ -// RUN: | FileCheck %s --check-prefix=NO-OUTPUT-ERROR -// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -nogpulib -fopenmp=libomp --offload-arch= \ -// RUN: --nvptx-arch-tool=%t/nvptx_arch_empty --amdgpu-arch-tool=%t/amdgpu_arch_empty %s 2>&1 \ -// RUN: | FileCheck %s --check-prefix=NO-OUTPUT-ERROR -// NO-OUTPUT-ERROR: error: failed to deduce triple for target architecture 'native'; specify the triple using '-fopenmp-targets' and '-Xopenmp-target' instead +// NO-OUTPUT-ERROR: error: cannot determine openmp architecture // case when amdgpu-arch succeeds. // RUN: %clang -### --target=x86_64-unknown-linux-gnu -nogpulib -fopenmp=libomp --offload-arch=native \ diff --git a/clang/test/Driver/print-multi-selection-flags.c b/clang/test/Driver/print-multi-selection-flags.c index 5f9383fbed8f4..b1a0a29ec4180 100644 --- a/clang/test/Driver/print-multi-selection-flags.c +++ b/clang/test/Driver/print-multi-selection-flags.c @@ -107,3 +107,39 @@ // CHECK-AARCH64-MULTILIB-CUSTOM-FLAG: --target=aarch64-unknown-none-eabi // CHECK-MULTILIB-CUSTOM-FLAG-DAG: -fmultilib-flag=foo // CHECK-MULTILIB-CUSTOM-FLAG-DAG: -fmultilib-flag=bar + +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -fropi | FileCheck --check-prefixes=CHECK-ROPI,CHECK-NO-RWPI,CHECK-NO-PIC %s +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -frwpi | FileCheck --check-prefixes=CHECK-NO-ROPI,CHECK-RWPI,CHECK-NO-PIC %s +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -fropi -frwpi | FileCheck --check-prefixes=CHECK-ROPI,CHECK-RWPI,CHECK-NO-PIC %s +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -fno-ropi -fno-rwpi | FileCheck --check-prefixes=CHECK-NO-ROPI,CHECK-NO-RWPI,CHECK-NO-PIC %s +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a | FileCheck --check-prefixes=CHECK-NO-ROPI,CHECK-NO-RWPI,CHECK-NO-PIC %s +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -fpic | FileCheck --check-prefixes=CHECK-NO-ROPI,CHECK-NO-RWPI,CHECK-PIC1 %s +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -fPIC | FileCheck --check-prefixes=CHECK-NO-ROPI,CHECK-NO-RWPI,CHECK-PIC2 %s +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -fpie | FileCheck --check-prefixes=CHECK-NO-ROPI,CHECK-NO-RWPI,CHECK-PIE1 %s +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -fPIE | FileCheck --check-prefixes=CHECK-NO-ROPI,CHECK-NO-RWPI,CHECK-PIE2 %s +// CHECK-PIC2: -fPIC +// CHECK-PIE2: -fPIE +// CHECK-NO-PIC: -fno-pic +// CHECK-NO-ROPI: -fno-ropi +// CHECK-NO-RWPI: -fno-rwpi +// CHECK-PIC1: -fpic +// CHECK-PIE1: -fpie +// CHECK-ROPI: -fropi +// CHECK-RWPI: -frwpi + +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -Os | FileCheck --check-prefix=CHECK-OPT-OS %s +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -Oz | FileCheck --check-prefix=CHECK-OPT-OZ %s +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a | FileCheck --check-prefix=CHECK-OPT %s +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -O1 | FileCheck --check-prefix=CHECK-OPT %s +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -O2 | FileCheck --check-prefix=CHECK-OPT %s +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -O3 | FileCheck --check-prefix=CHECK-OPT %s +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=aarch64-none-eabi -Os | FileCheck --check-prefix=CHECK-OPT-OS %s +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=aarch64-none-eabi -Oz | FileCheck --check-prefix=CHECK-OPT-OZ %s +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=aarch64-none-eabi | FileCheck --check-prefix=CHECK-OPT %s +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=aarch64-none-eabi -O1 | FileCheck --check-prefix=CHECK-OPT %s +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=aarch64-none-eabi -O2 | FileCheck --check-prefix=CHECK-OPT %s +// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=aarch64-none-eabi -O3 | FileCheck --check-prefix=CHECK-OPT %s +// CHECK-OPT-OZ: -Oz +// CHECK-OPT-OS: -Os +// CHECK-OPT-NOT: -Oz +// CHECK-OPT-NOT: -Os diff --git a/clang/test/FixIt/fixit-format-ios-nopedantic.m b/clang/test/FixIt/fixit-format-ios-nopedantic.m index db9ac797c2472..836a4b5372f13 100644 --- a/clang/test/FixIt/fixit-format-ios-nopedantic.m +++ b/clang/test/FixIt/fixit-format-ios-nopedantic.m @@ -1,5 +1,5 @@ // RUN: cp %s %t -// RUN: %clang_cc1 -triple thumbv7-apple-ios8.0.0 -Wformat -Werror -fixit %t +// RUN: %clang_cc1 -triple thumbv7-apple-ios8.0.0 -Wformat -fixit %t int printf(const char *restrict, ...); typedef unsigned int NSUInteger; diff --git a/clang/test/FixIt/format.m b/clang/test/FixIt/format.m index 950765bad9339..e97ae10c974aa 100644 --- a/clang/test/FixIt/format.m +++ b/clang/test/FixIt/format.m @@ -237,14 +237,14 @@ void testSizeTypes(void) { printf("%zu", 0.f); // expected-warning-re{{format specifies type 'size_t' (aka '{{.+}}') but the argument has type 'float'}} // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%f" - printf("%zd", 0.f); // expected-warning-re{{format specifies type 'ssize_t' (aka '{{.+}}') but the argument has type 'float'}} + printf("%zd", 0.f); // expected-warning-re{{format specifies type 'signed size_t' (aka '{{.+}}') but the argument has type 'float'}} // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%f" short x; #if !defined(__ANDROID__) && !defined(__Fuchsia__) - printf("%zn", &x); // expected-warning-re{{format specifies type 'ssize_t *' (aka '{{.+}}') but the argument has type 'short *'}} + printf("%zn", &x); // expected-warning-re{{format specifies type 'signed size_t *' (aka '{{.+}}') but the argument has type 'short *'}} #else - printf("%zn", &x); // expected-warning-re{{format specifies type 'ssize_t *' (aka '{{.+}}') but the argument has type 'short *'}} + printf("%zn", &x); // expected-warning-re{{format specifies type 'signed size_t *' (aka '{{.+}}') but the argument has type 'short *'}} // expected-warning@-1 {{'%n' specifier not supported on this platform}} #endif // !defined(__ANDROID__) && !defined(__Fuchsia__) // PrintfSpecifier::fixType doesn't handle %n, so a fix-it is not emitted, diff --git a/clang/test/Headers/spirv_ids.cpp b/clang/test/Headers/spirv_ids.cpp index 0cd74dbca53aa..466be5deee87a 100644 --- a/clang/test/Headers/spirv_ids.cpp +++ b/clang/test/Headers/spirv_ids.cpp @@ -53,58 +53,58 @@ // CHECK: call i32 @llvm.spv.subgroup.id() // CHECK: call i32 @llvm.spv.subgroup.local.invocation.id() -// NV: call noundef i64 @_Z21__spirv_NumWorkgroupsi(i32 noundef 0) #2 -// NV: call noundef i64 @_Z21__spirv_NumWorkgroupsi(i32 noundef 1) #2 -// NV: call noundef i64 @_Z21__spirv_NumWorkgroupsi(i32 noundef 2) #2 -// NV: call noundef i64 @_Z21__spirv_WorkgroupSizei(i32 noundef 0) #2 -// NV: call noundef i64 @_Z21__spirv_WorkgroupSizei(i32 noundef 1) #2 -// NV: call noundef i64 @_Z21__spirv_WorkgroupSizei(i32 noundef 2) #2 -// NV: call noundef i64 @_Z19__spirv_WorkgroupIdi(i32 noundef 0) #2 -// NV: call noundef i64 @_Z19__spirv_WorkgroupIdi(i32 noundef 1) #2 -// NV: call noundef i64 @_Z19__spirv_WorkgroupIdi(i32 noundef 2) #2 -// NV: call noundef i64 @_Z25__spirv_LocalInvocationIdi(i32 noundef 0) #2 -// NV: call noundef i64 @_Z25__spirv_LocalInvocationIdi(i32 noundef 1) #2 -// NV: call noundef i64 @_Z25__spirv_LocalInvocationIdi(i32 noundef 2) #2 -// NV: call noundef i64 @_Z26__spirv_GlobalInvocationIdi(i32 noundef 0) #2 -// NV: call noundef i64 @_Z26__spirv_GlobalInvocationIdi(i32 noundef 1) #2 -// NV: call noundef i64 @_Z26__spirv_GlobalInvocationIdi(i32 noundef 2) #2 -// NV: call noundef i64 @_Z18__spirv_GlobalSizei(i32 noundef 0) #2 -// NV: call noundef i64 @_Z18__spirv_GlobalSizei(i32 noundef 1) #2 -// NV: call noundef i64 @_Z18__spirv_GlobalSizei(i32 noundef 2) #2 -// NV: call noundef i64 @_Z20__spirv_GlobalOffseti(i32 noundef 0) #2 -// NV: call noundef i64 @_Z20__spirv_GlobalOffseti(i32 noundef 1) #2 -// NV: call noundef i64 @_Z20__spirv_GlobalOffseti(i32 noundef 2) #2 -// NV: call noundef i32 @_Z20__spirv_SubgroupSizev() #2 -// NV: call noundef i32 @_Z23__spirv_SubgroupMaxSizev() #2 -// NV: call noundef i32 @_Z20__spirv_NumSubgroupsv() #2 -// NV: call noundef i32 @_Z18__spirv_SubgroupIdv() #2 -// NV: call noundef i32 @_Z33__spirv_SubgroupLocalInvocationIdv() #2 +// NV: call noundef i64 @_Z28__spirv_BuiltInNumWorkgroupsi(i32 noundef 0) #2 +// NV: call noundef i64 @_Z28__spirv_BuiltInNumWorkgroupsi(i32 noundef 1) #2 +// NV: call noundef i64 @_Z28__spirv_BuiltInNumWorkgroupsi(i32 noundef 2) #2 +// NV: call noundef i64 @_Z28__spirv_BuiltInWorkgroupSizei(i32 noundef 0) #2 +// NV: call noundef i64 @_Z28__spirv_BuiltInWorkgroupSizei(i32 noundef 1) #2 +// NV: call noundef i64 @_Z28__spirv_BuiltInWorkgroupSizei(i32 noundef 2) #2 +// NV: call noundef i64 @_Z26__spirv_BuiltInWorkgroupIdi(i32 noundef 0) #2 +// NV: call noundef i64 @_Z26__spirv_BuiltInWorkgroupIdi(i32 noundef 1) #2 +// NV: call noundef i64 @_Z26__spirv_BuiltInWorkgroupIdi(i32 noundef 2) #2 +// NV: call noundef i64 @_Z32__spirv_BuiltInLocalInvocationIdi(i32 noundef 0) #2 +// NV: call noundef i64 @_Z32__spirv_BuiltInLocalInvocationIdi(i32 noundef 1) #2 +// NV: call noundef i64 @_Z32__spirv_BuiltInLocalInvocationIdi(i32 noundef 2) #2 +// NV: call noundef i64 @_Z33__spirv_BuiltInGlobalInvocationIdi(i32 noundef 0) #2 +// NV: call noundef i64 @_Z33__spirv_BuiltInGlobalInvocationIdi(i32 noundef 1) #2 +// NV: call noundef i64 @_Z33__spirv_BuiltInGlobalInvocationIdi(i32 noundef 2) #2 +// NV: call noundef i64 @_Z25__spirv_BuiltInGlobalSizei(i32 noundef 0) #2 +// NV: call noundef i64 @_Z25__spirv_BuiltInGlobalSizei(i32 noundef 1) #2 +// NV: call noundef i64 @_Z25__spirv_BuiltInGlobalSizei(i32 noundef 2) #2 +// NV: call noundef i64 @_Z27__spirv_BuiltInGlobalOffseti(i32 noundef 0) #2 +// NV: call noundef i64 @_Z27__spirv_BuiltInGlobalOffseti(i32 noundef 1) #2 +// NV: call noundef i64 @_Z27__spirv_BuiltInGlobalOffseti(i32 noundef 2) #2 +// NV: call noundef i32 @_Z27__spirv_BuiltInSubgroupSizev() #2 +// NV: call noundef i32 @_Z30__spirv_BuiltInSubgroupMaxSizev() #2 +// NV: call noundef i32 @_Z27__spirv_BuiltInNumSubgroupsv() #2 +// NV: call noundef i32 @_Z25__spirv_BuiltInSubgroupIdv() #2 +// NV: call noundef i32 @_Z40__spirv_BuiltInSubgroupLocalInvocationIdv() #2 void test_id_and_range() { - __spirv_NumWorkgroups(0); - __spirv_NumWorkgroups(1); - __spirv_NumWorkgroups(2); - __spirv_WorkgroupSize(0); - __spirv_WorkgroupSize(1); - __spirv_WorkgroupSize(2); - __spirv_WorkgroupId(0); - __spirv_WorkgroupId(1); - __spirv_WorkgroupId(2); - __spirv_LocalInvocationId(0); - __spirv_LocalInvocationId(1); - __spirv_LocalInvocationId(2); - __spirv_GlobalInvocationId(0); - __spirv_GlobalInvocationId(1); - __spirv_GlobalInvocationId(2); - __spirv_GlobalSize(0); - __spirv_GlobalSize(1); - __spirv_GlobalSize(2); - __spirv_GlobalOffset(0); - __spirv_GlobalOffset(1); - __spirv_GlobalOffset(2); - unsigned int ssize = __spirv_SubgroupSize(); - unsigned int smax = __spirv_SubgroupMaxSize(); - unsigned int snum = __spirv_NumSubgroups(); - unsigned int sid = __spirv_SubgroupId(); - unsigned int sinvocid = __spirv_SubgroupLocalInvocationId(); + __spirv_BuiltInNumWorkgroups(0); + __spirv_BuiltInNumWorkgroups(1); + __spirv_BuiltInNumWorkgroups(2); + __spirv_BuiltInWorkgroupSize(0); + __spirv_BuiltInWorkgroupSize(1); + __spirv_BuiltInWorkgroupSize(2); + __spirv_BuiltInWorkgroupId(0); + __spirv_BuiltInWorkgroupId(1); + __spirv_BuiltInWorkgroupId(2); + __spirv_BuiltInLocalInvocationId(0); + __spirv_BuiltInLocalInvocationId(1); + __spirv_BuiltInLocalInvocationId(2); + __spirv_BuiltInGlobalInvocationId(0); + __spirv_BuiltInGlobalInvocationId(1); + __spirv_BuiltInGlobalInvocationId(2); + __spirv_BuiltInGlobalSize(0); + __spirv_BuiltInGlobalSize(1); + __spirv_BuiltInGlobalSize(2); + __spirv_BuiltInGlobalOffset(0); + __spirv_BuiltInGlobalOffset(1); + __spirv_BuiltInGlobalOffset(2); + unsigned int ssize = __spirv_BuiltInSubgroupSize(); + unsigned int smax = __spirv_BuiltInSubgroupMaxSize(); + unsigned int snum = __spirv_BuiltInNumSubgroups(); + unsigned int sid = __spirv_BuiltInSubgroupId(); + unsigned int sinvocid = __spirv_BuiltInSubgroupLocalInvocationId(); } diff --git a/clang/test/Headers/stdarg.cpp b/clang/test/Headers/stdarg.cpp index 20bf17caf15f7..bfc3af11a23b6 100644 --- a/clang/test/Headers/stdarg.cpp +++ b/clang/test/Headers/stdarg.cpp @@ -15,8 +15,8 @@ #include -// AARCH64-C: define {{.*}} @f(i32 noundef %n, ptr noundef %list) -// AARCH64-CXX: define {{.*}} @_Z1fiSt9__va_list(i32 noundef %n, ptr noundef %list) +// AARCH64-C: define {{.*}} @f(i32 noundef %n, ptr dead_on_return noundef %list) +// AARCH64-CXX: define {{.*}} @_Z1fiSt9__va_list(i32 noundef %n, ptr dead_on_return noundef %list) // X86_64-C: define {{.*}} @f(i32 noundef %n, ptr noundef %list) // X86_64-CXX: define {{.*}} @_Z1fiP13__va_list_tag(i32 noundef %n, ptr noundef %list) // PPC64-C: define {{.*}} @f(i32 noundef signext %n, ptr noundef %list) diff --git a/clang/test/Interpreter/pretty-print.c b/clang/test/Interpreter/pretty-print.c index d21749a649e1c..56488a164719b 100644 --- a/clang/test/Interpreter/pretty-print.c +++ b/clang/test/Interpreter/pretty-print.c @@ -3,9 +3,88 @@ // RUN: cat %s | clang-repl -Xcc -xc | FileCheck %s // RUN: cat %s | clang-repl -Xcc -std=c++11 | FileCheck %s -// Fails with `Symbols not found: [ __clang_Interpreter_SetValueNoAlloc ]`. // UNSUPPORTED: hwasan + +char c = 'a'; c +// CHECK: (char) 'a' + const char* c_str = "Hello, world!"; c_str +// CHECK-NEXT: (const char *) "Hello, world!" + +c_str = "Goodbye, world!"; c_str +// CHECK-NEXT: (const char *) "Goodbye, world!" + +const char* c_null_str = 0; c_null_str +// CHECK-NEXT: (const char *) 0 + +"Hello, world" +// CHECK-NEXT: ({{(const )?}}char[13]) "Hello, world" + +int x = 42; x +// CHECK-NEXT: (int) 42 + +&x +// CHECK-NEXT: (int *) 0x{{[0-9a-f]+}} + +x - 2 +// CHECK-NEXT: (int) 40 + +float f = 4.2f; f +// CHECK-NEXT: (float) 4.20000f + +double d = 4.21; d +// CHECK-NEXT: (double) 4.2100000 + +long double tau = 6.2831853; tau +// CHECK-NEXT: (long double) 6.28318530000L + +int foo() { return 42; } foo() +// CHECK-NEXT: (int) 42 + +void bar(int a, float b) {} bar +// CHECK-NEXT: (void (int, float)) Function @0x{{[0-9a-f]+}} +// CHECK-NEXT: void bar(int a, float b) { + +bar +// CHECK: (void (int, float)) Function @0x{{[0-9a-f]+}} +// CHECK-NEXT: void bar(int a, float b) { + +// Arrays. + +int arr[3] = {1,2,3}; arr +// CHECK: (int[3]) { 1, 2, 3 } + +double darr[3][4] = { {1,2,3,4}, {5,6,7,8}, {9,10,11,12} }; darr +// CHECK-NEXT: (double[3][4]) { { 1.0, 2.0, 3.0, 4.0 }, { 5.0, 6.0, 7.0, 8.0 }, { 9.0, 10.0, 11.0, 12.0 } } + +float farr[2][1] = { {0}, {3.14}}; farr +// CHECK-NEXT: (float[2][1]) { { 0.0f }, { 3.14000f } } + +0./0. +// CHECK-NEXT: (double) nan + +1.0f / 0.0f +// CHECK-NEXT: (float) inf + +0.00001f +// CHECK-NEXT: (float) 1.00000e-05f + +int * ptr = (int*)0x123; ptr +// CHECK-NEXT: (int *) 0x123 + +int * null_ptr = (int*)0; null_ptr +// CHECK-NEXT: (int *) 0x0 + +// TODO: _Bool, _Complex, _Atomic, and _BitInt +// union U { int I; float F; } u; u.I = 12; u.I +// TODO-CHECK-NEXT: (int) 12 +// struct S1{} s1; s1 +// TODO-CHECK-NEXT: (S1 &) @0x{{[0-9a-f]+}} + +// struct S2 {int d;} E = {22}; E +// TODO-CHECK-NEXT: (struct S2 &) @0x{{[0-9a-f]+}} +// E.d +// TODO-CHECK-NEXT: (int) 22 -// CHECK: Not implement yet. +%quit diff --git a/clang/test/Interpreter/pretty-print.cpp b/clang/test/Interpreter/pretty-print.cpp new file mode 100644 index 0000000000000..fd79d315e48ba --- /dev/null +++ b/clang/test/Interpreter/pretty-print.cpp @@ -0,0 +1,73 @@ +// RUN: clang-repl "int i = 10;" 'extern "C" int printf(const char*,...);' \ +// RUN: 'auto r1 = printf("i = %d\n", i);' | FileCheck --check-prefix=CHECK-DRIVER %s +// UNSUPPORTED: system-aix +// CHECK-DRIVER: i = 10 +// RUN: cat %s | clang-repl -Xcc -std=c++11 -Xcc -fno-delayed-template-parsing | FileCheck %s +extern "C" int printf(const char*,...); + +"ab" +// CHECK: (const char[3]) "ab" + +123456 +// CHECK-NEXT: (int) 123456 + +char ch[2] = {'1','a'}; ch +// CHECK-NEXT: (char[2]) { '1', 'a' } + +char chnull[3] = {'1','a', '\0'}; chnull +// CHECK-NEXT: (char[3]) "1a" + +char ch_arr[2][3][1] = {{{'a'}, {'b'}, {'c'}}, {{'d'}, {'e'}, {'f'}}}; ch_arr +// CHECK: (char[2][3][1]) { { { 'a' }, { 'b' }, { 'c' } }, { { 'd' }, { 'e' }, { 'f' } } } +struct S3 { int* p; S3() { p = new int(42); } ~S3() { delete p; } }; +S3{} +// CHECK-NEXT: (S3) @0x{{[0-9a-f]+}} +S3 s3; +s3 +// CHECK-NEXT: (S3 &) @0x{{[0-9a-f]+}} + +struct S4 { ~S4() { printf("~S4()\n"); }}; +S4{} +// CHECK-NEXT: (S4) @0x{{[0-9a-f]+}} +// TODO-CHECK-NEXT: ~S4() + +enum Enum{ e1 = -12, e2, e3=33, e4, e5 = 33}; +e2 +// CHECK-NEXT: (Enum) (e2) : int -11 +::e1 +// CHECK-NEXT: (Enum) (e1) : int -12 + +enum class Color { R = 0, G, B }; +Color::R +// CHECK-NEXT: (Color) (Color::R) : int 0 + + +// Lambdas. + +auto Lambda1 = []{}; +Lambda1 +// CHECK-NEXT: ((lambda) &) @0x{{[0-9a-f]+}} +[]{} +// CHECK-NEXT: ((lambda at input_line_{{[0-9]+}}:1:1)) @0x{{[0-9a-f]+}} + +template struct F{ enum {RET=F::RET*n} ; }; +template<> struct F<0> { enum {RET = 1}; }; +F<7>::RET +// CHECK-NEXT: (F<7>::(unnamed enum at input_line_{{[0-9]+}}:1:27)) (F<7>::RET) : unsigned int 5040 + +struct S5 { int foo() { return 42; }}; +&S5::foo +// CHECK-NEXT: (int (S5::*)()) Function @0x{{[0-9a-f]+}} + +// int i = 12; +// int &iref = i; +// iref +// // TODO-CHECK-NEXT: (int &) 12 + +// int &&rref = 100; +// rref + +// // TODO-CHECK-NEXT: (int &&) 100 + +%quit + diff --git a/clang/test/Modules/cxx20-10-2-ex1.cpp b/clang/test/Modules/cxx20-10-2-ex1.cpp index 0cd6f77466f4b..749b15213098a 100644 --- a/clang/test/Modules/cxx20-10-2-ex1.cpp +++ b/clang/test/Modules/cxx20-10-2-ex1.cpp @@ -14,7 +14,7 @@ export int x; module; #include "std-10-2-ex1.h" -// expected-error@std-10-2-ex1.h:* {{export declaration can only be used within a module purview}} +// expected-error@std-10-2-ex1.h:* {{export declaration can only be used within a module interface}} export module M1; export namespace {} // expected-error {{anonymous namespaces cannot be exported}} diff --git a/clang/test/Modules/cxx20-export-import.cpp b/clang/test/Modules/cxx20-export-import.cpp index 0b505668e8589..c14883e575575 100644 --- a/clang/test/Modules/cxx20-export-import.cpp +++ b/clang/test/Modules/cxx20-export-import.cpp @@ -11,4 +11,4 @@ export module dummy; //--- test.cpp -export import dummy; // expected-error {{export declaration can only be used within a module purview}} +export import dummy; // expected-error {{export declaration can only be used within a module interface}} diff --git a/clang/test/Modules/cxx20-import-diagnostics-a.cpp b/clang/test/Modules/cxx20-import-diagnostics-a.cpp index 1b38259e0358c..72a31ea1d7d78 100644 --- a/clang/test/Modules/cxx20-import-diagnostics-a.cpp +++ b/clang/test/Modules/cxx20-import-diagnostics-a.cpp @@ -110,7 +110,7 @@ module; module AOK1; -export import C; // expected-error {{export declaration can only be used within a module purview}} +export import C; // expected-error {{export declaration can only be used within a module interface}} int theAnswer () { return 42; } diff --git a/clang/test/Modules/export-in-non-modules.cpp b/clang/test/Modules/export-in-non-modules.cpp index 69360eb46d774..7b2575c60f1fd 100644 --- a/clang/test/Modules/export-in-non-modules.cpp +++ b/clang/test/Modules/export-in-non-modules.cpp @@ -1,4 +1,4 @@ // RUN: %clang_cc1 -std=c++20 %s -fsyntax-only -verify -export struct Unit { // expected-error {{export declaration can only be used within a module purview}} +export struct Unit { // expected-error {{export declaration can only be used within a module interface}} bool operator<(const Unit &); }; diff --git a/clang/test/Modules/mingw-exceptions.cppm b/clang/test/Modules/mingw-exceptions.cppm index db7aa2ce90a94..be9d61d7d3418 100644 --- a/clang/test/Modules/mingw-exceptions.cppm +++ b/clang/test/Modules/mingw-exceptions.cppm @@ -1,5 +1,6 @@ // REQUIRES: x86-registered-target -// RUN: %clang -target x86_64-windows-gnu -x c++-module -std=gnu++23 -c -o /dev/null -Xclang -disable-llvm-passes %s +// RUN: %clang -target x86_64-windows-gnu -x c++-module -std=gnu++23 -fno-modules-reduced-bmi \ +// RUN: -c -o /dev/null -Xclang -disable-llvm-passes %s // Make sure the command succeeds and doesn't break on the -exception-model flag in cc1. export module empty; diff --git a/clang/test/OpenMP/for_firstprivate_codegen.cpp b/clang/test/OpenMP/for_firstprivate_codegen.cpp index 0255e1e3d4aea..83b5939799642 100644 --- a/clang/test/OpenMP/for_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/for_firstprivate_codegen.cpp @@ -427,7 +427,7 @@ int main() { // CHECK1-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[S_ARR]], i64 1 // CHECK1-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], i32 noundef 2) // CHECK1-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8, !nonnull [[META3:![0-9]+]], !align [[META4:![0-9]+]] // CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB2]], i32 4, ptr @_Z5tmainIiET_v.omp_outlined, ptr [[T_VAR]], ptr [[VEC]], ptr [[S_ARR]], ptr [[TMP0]]) // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0 @@ -469,7 +469,7 @@ int main() { // CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8 // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK1-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP0]], i32 0, i32 0 // CHECK1-NEXT: [[TMP1:%.*]] = load float, ptr [[F2]], align 4 // CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -543,12 +543,12 @@ int main() { // CHECK1-NEXT: store ptr [[VEC]], ptr [[VEC_ADDR]], align 8 // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[T_VAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[T_VAR_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] +// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK1-NEXT: store ptr [[TMP3]], ptr [[TMP]], align 8 -// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK1-NEXT: store ptr [[TMP4]], ptr [[_TMP1]], align 8 // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK1-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 @@ -572,7 +572,7 @@ int main() { // CHECK1-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP6]] // CHECK1-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE6]], label [[OMP_ARRAYCPY_BODY]] // CHECK1: omp.arraycpy.done6: -// CHECK1-NEXT: [[TMP7:%.*]] = load ptr, ptr [[_TMP1]], align 8 +// CHECK1-NEXT: [[TMP7:%.*]] = load ptr, ptr [[_TMP1]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK1-NEXT: call void @_ZN2StC1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP8]]) // CHECK1-NEXT: call void @_ZN1SIiEC1ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[VAR7]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP7]], ptr noundef [[AGG_TMP8]]) // CHECK1-NEXT: call void @_ZN2StD1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP8]]) #[[ATTR2]] @@ -611,7 +611,7 @@ int main() { // CHECK1-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP17]] to i64 // CHECK1-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i32], ptr [[VEC4]], i64 0, i64 [[IDXPROM]] // CHECK1-NEXT: store i32 [[TMP16]], ptr [[ARRAYIDX]], align 4 -// CHECK1-NEXT: [[TMP18:%.*]] = load ptr, ptr [[_TMP9]], align 8 +// CHECK1-NEXT: [[TMP18:%.*]] = load ptr, ptr [[_TMP9]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK1-NEXT: [[TMP19:%.*]] = load i32, ptr [[I]], align 4 // CHECK1-NEXT: [[IDXPROM11:%.*]] = sext i32 [[TMP19]] to i64 // CHECK1-NEXT: [[ARRAYIDX12:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR5]], i64 0, i64 [[IDXPROM11]] @@ -711,7 +711,7 @@ int main() { // CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8 // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK1-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0]], ptr [[TMP0]], i32 0, i32 0 // CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[F2]], align 4 // CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -1044,8 +1044,8 @@ int main() { // CHECK4-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK4-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8 // CHECK4-NEXT: store ptr [[SIVAR]], ptr [[SIVAR_ADDR]], align 8 -// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[SIVAR_ADDR]], align 8 -// CHECK4-NEXT: [[TMP1:%.*]] = load ptr, ptr @g1, align 8 +// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[SIVAR_ADDR]], align 8, !nonnull [[META3:![0-9]+]], !align [[META4:![0-9]+]] +// CHECK4-NEXT: [[TMP1:%.*]] = load ptr, ptr @g1, align 8, !nonnull [[META3]], !align [[META4]] // CHECK4-NEXT: store ptr [[TMP1]], ptr [[TMP]], align 8 // CHECK4-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK4-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 @@ -1086,7 +1086,7 @@ int main() { // CHECK4-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]] // CHECK4-NEXT: store i32 [[ADD]], ptr [[I]], align 4 // CHECK4-NEXT: store i32 1, ptr [[G]], align 4 -// CHECK4-NEXT: [[TMP13:%.*]] = load ptr, ptr [[_TMP2]], align 8 +// CHECK4-NEXT: [[TMP13:%.*]] = load ptr, ptr [[_TMP2]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK4-NEXT: store volatile i32 1, ptr [[TMP13]], align 4 // CHECK4-NEXT: store i32 2, ptr [[SIVAR3]], align 4 // CHECK4-NEXT: [[BLOCK_ISA:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, i32, i32 }>, ptr [[BLOCK]], i32 0, i32 0 @@ -1103,7 +1103,7 @@ int main() { // CHECK4-NEXT: [[TMP14:%.*]] = load volatile i32, ptr [[G]], align 4 // CHECK4-NEXT: store volatile i32 [[TMP14]], ptr [[BLOCK_CAPTURED]], align 8 // CHECK4-NEXT: [[BLOCK_CAPTURED5:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, i32, i32 }>, ptr [[BLOCK]], i32 0, i32 5 -// CHECK4-NEXT: [[TMP15:%.*]] = load ptr, ptr [[_TMP2]], align 8 +// CHECK4-NEXT: [[TMP15:%.*]] = load ptr, ptr [[_TMP2]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK4-NEXT: store ptr [[TMP15]], ptr [[BLOCK_CAPTURED5]], align 8 // CHECK4-NEXT: [[BLOCK_CAPTURED6:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, i32, i32 }>, ptr [[BLOCK]], i32 0, i32 7 // CHECK4-NEXT: [[TMP16:%.*]] = load i32, ptr [[SIVAR3]], align 4 @@ -1137,7 +1137,7 @@ int main() { // CHECK4-NEXT: [[BLOCK_CAPTURE_ADDR:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, i32, i32 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 6 // CHECK4-NEXT: store i32 2, ptr [[BLOCK_CAPTURE_ADDR]], align 8 // CHECK4-NEXT: [[BLOCK_CAPTURE_ADDR1:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, i32, i32 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 5 -// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BLOCK_CAPTURE_ADDR1]], align 8 +// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BLOCK_CAPTURE_ADDR1]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK4-NEXT: store i32 2, ptr [[TMP0]], align 4 // CHECK4-NEXT: [[BLOCK_CAPTURE_ADDR2:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, i32, i32 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 7 // CHECK4-NEXT: store i32 4, ptr [[BLOCK_CAPTURE_ADDR2]], align 4 diff --git a/clang/test/OpenMP/parallel_firstprivate_codegen.cpp b/clang/test/OpenMP/parallel_firstprivate_codegen.cpp index 93e71b9a8312e..441e809dc59e5 100644 --- a/clang/test/OpenMP/parallel_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/parallel_firstprivate_codegen.cpp @@ -350,9 +350,9 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 // CHECK1-NEXT: store i32 [[SIVAR]], ptr [[SIVAR_ADDR]], align 4 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META4:![0-9]+]], !align [[META5:![0-9]+]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK1-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[VEC1]], ptr align 4 [[TMP0]], i32 8, i1 false) // CHECK1-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR2]], i32 0, i32 0 // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN]], i32 2 @@ -524,7 +524,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK1-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 0 // CHECK1-NEXT: store i8 [[BF_SET]], ptr [[B]], align 4 // CHECK1-NEXT: [[C:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 2 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[D_ADDR]], align 4 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[D_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK1-NEXT: store ptr [[TMP0]], ptr [[C]], align 4 // CHECK1-NEXT: [[A3:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 0 // CHECK1-NEXT: store ptr [[A3]], ptr [[A2]], align 4 @@ -535,22 +535,22 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK1-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_ASHR]] to i32 // CHECK1-NEXT: store i32 [[BF_CAST]], ptr [[B4]], align 4 // CHECK1-NEXT: [[C8:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 2 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[C8]], align 4 +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[C8]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK1-NEXT: store ptr [[TMP1]], ptr [[C7]], align 4 // CHECK1-NEXT: [[E9:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 3 // CHECK1-NEXT: store ptr [[E9]], ptr [[E]], align 4 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A2]], align 4 +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A2]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4 // CHECK1-NEXT: store i32 [[TMP3]], ptr [[A_CASTED]], align 4 // CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[A_CASTED]], align 4 // CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[B4]], align 4 // CHECK1-NEXT: store i32 [[TMP5]], ptr [[B_CASTED]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = load i32, ptr [[B_CASTED]], align 4 -// CHECK1-NEXT: [[TMP7:%.*]] = load ptr, ptr [[C7]], align 4 +// CHECK1-NEXT: [[TMP7:%.*]] = load ptr, ptr [[C7]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4 // CHECK1-NEXT: store i32 [[TMP8]], ptr [[C_CASTED]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = load i32, ptr [[C_CASTED]], align 4 -// CHECK1-NEXT: [[TMP10:%.*]] = load ptr, ptr [[E]], align 4 +// CHECK1-NEXT: [[TMP10:%.*]] = load ptr, ptr [[E]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 5, ptr @_ZN2SSC2ERi.omp_outlined, ptr [[THIS1]], i32 [[TMP4]], i32 [[TMP6]], i32 [[TMP9]], ptr [[TMP10]]) // CHECK1-NEXT: ret void // @@ -578,25 +578,25 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK1-NEXT: store i32 [[C]], ptr [[C_ADDR]], align 4 // CHECK1-NEXT: store ptr [[E]], ptr [[E_ADDR]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[E_ADDR]], align 4 +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[E_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK1-NEXT: store ptr [[A_ADDR]], ptr [[TMP]], align 4 // CHECK1-NEXT: store ptr [[C_ADDR]], ptr [[_TMP1]], align 4 // CHECK1-NEXT: store ptr [[TMP1]], ptr [[_TMP2]], align 4 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[_TMP2]], align 4 +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[_TMP2]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK1-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[E3]], ptr align 4 [[TMP2]], i32 16, i1 false) // CHECK1-NEXT: store ptr [[E3]], ptr [[_TMP4]], align 4 -// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4 // CHECK1-NEXT: [[INC:%.*]] = add nsw i32 [[TMP4]], 1 // CHECK1-NEXT: store i32 [[INC]], ptr [[TMP3]], align 4 // CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[B_ADDR]], align 4 // CHECK1-NEXT: [[DEC:%.*]] = add nsw i32 [[TMP5]], -1 // CHECK1-NEXT: store i32 [[DEC]], ptr [[B_ADDR]], align 4 -// CHECK1-NEXT: [[TMP6:%.*]] = load ptr, ptr [[_TMP1]], align 4 +// CHECK1-NEXT: [[TMP6:%.*]] = load ptr, ptr [[_TMP1]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK1-NEXT: [[TMP7:%.*]] = load i32, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP7]], 1 // CHECK1-NEXT: store i32 [[DIV]], ptr [[TMP6]], align 4 -// CHECK1-NEXT: [[TMP8:%.*]] = load ptr, ptr [[_TMP4]], align 4 +// CHECK1-NEXT: [[TMP8:%.*]] = load ptr, ptr [[_TMP4]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK1-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x i32], ptr [[TMP8]], i32 0, i32 2 // CHECK1-NEXT: store i32 1111, ptr [[ARRAYIDX]], align 4 // CHECK1-NEXT: ret void @@ -656,7 +656,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4 // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 // CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK1-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP0]], i32 0, i32 0 // CHECK1-NEXT: [[TMP1:%.*]] = load float, ptr [[F2]], align 4 // CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -738,9 +738,9 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK1-NEXT: store i32 [[T_VAR]], ptr [[T_VAR_ADDR]], align 4 // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK1-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 128 [[VEC1]], ptr align 128 [[TMP0]], i32 8, i1 false) // CHECK1-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR2]], i32 0, i32 0 // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN]], i32 2 @@ -840,7 +840,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK1-NEXT: store i32 0, ptr [[A]], align 4 // CHECK1-NEXT: [[A3:%.*]] = getelementptr inbounds nuw [[STRUCT_SST]], ptr [[THIS1]], i32 0, i32 0 // CHECK1-NEXT: store ptr [[A3]], ptr [[A2]], align 4 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A2]], align 4 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A2]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4 // CHECK1-NEXT: store i32 [[TMP1]], ptr [[A_CASTED]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = load i32, ptr [[A_CASTED]], align 4 @@ -862,7 +862,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK1-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 // CHECK1-NEXT: store ptr [[A_ADDR]], ptr [[TMP]], align 4 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK1-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[INC:%.*]] = add nsw i32 [[TMP2]], 1 // CHECK1-NEXT: store i32 [[INC]], ptr [[TMP1]], align 4 @@ -896,7 +896,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4 // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 // CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK1-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0]], ptr [[TMP0]], i32 0, i32 0 // CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[F2]], align 4 // CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -965,7 +965,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK3-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 0 // CHECK3-NEXT: store i8 [[BF_SET]], ptr [[B]], align 4 // CHECK3-NEXT: [[C:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 2 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[D_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[D_ADDR]], align 4, !nonnull [[META4:![0-9]+]], !align [[META5:![0-9]+]] // CHECK3-NEXT: store ptr [[TMP0]], ptr [[C]], align 4 // CHECK3-NEXT: [[A3:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 0 // CHECK3-NEXT: store ptr [[A3]], ptr [[A2]], align 4 @@ -976,22 +976,22 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK3-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_ASHR]] to i32 // CHECK3-NEXT: store i32 [[BF_CAST]], ptr [[B4]], align 4 // CHECK3-NEXT: [[C8:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 2 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[C8]], align 4 +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[C8]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK3-NEXT: store ptr [[TMP1]], ptr [[C7]], align 4 // CHECK3-NEXT: [[E9:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 3 // CHECK3-NEXT: store ptr [[E9]], ptr [[E]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A2]], align 4 +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A2]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK3-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4 // CHECK3-NEXT: store i32 [[TMP3]], ptr [[A_CASTED]], align 4 // CHECK3-NEXT: [[TMP4:%.*]] = load i32, ptr [[A_CASTED]], align 4 // CHECK3-NEXT: [[TMP5:%.*]] = load i32, ptr [[B4]], align 4 // CHECK3-NEXT: store i32 [[TMP5]], ptr [[B_CASTED]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = load i32, ptr [[B_CASTED]], align 4 -// CHECK3-NEXT: [[TMP7:%.*]] = load ptr, ptr [[C7]], align 4 +// CHECK3-NEXT: [[TMP7:%.*]] = load ptr, ptr [[C7]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK3-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4 // CHECK3-NEXT: store i32 [[TMP8]], ptr [[C_CASTED]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = load i32, ptr [[C_CASTED]], align 4 -// CHECK3-NEXT: [[TMP10:%.*]] = load ptr, ptr [[E]], align 4 +// CHECK3-NEXT: [[TMP10:%.*]] = load ptr, ptr [[E]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1:[0-9]+]], i32 5, ptr @_ZN2SSC2ERi.omp_outlined, ptr [[THIS1]], i32 [[TMP4]], i32 [[TMP6]], i32 [[TMP9]], ptr [[TMP10]]) // CHECK3-NEXT: ret void // @@ -1020,22 +1020,22 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK3-NEXT: store i32 [[C]], ptr [[C_ADDR]], align 4 // CHECK3-NEXT: store ptr [[E]], ptr [[E_ADDR]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[E_ADDR]], align 4 +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[E_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK3-NEXT: store ptr [[A_ADDR]], ptr [[TMP]], align 4 // CHECK3-NEXT: store ptr [[C_ADDR]], ptr [[_TMP1]], align 4 // CHECK3-NEXT: store ptr [[TMP1]], ptr [[_TMP2]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[_TMP2]], align 4 +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[_TMP2]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK3-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[E3]], ptr align 4 [[TMP2]], i32 16, i1 false) // CHECK3-NEXT: store ptr [[E3]], ptr [[_TMP4]], align 4 // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 0 // CHECK3-NEXT: store ptr [[TMP0]], ptr [[TMP3]], align 4 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 1 -// CHECK3-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK3-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK3-NEXT: store ptr [[TMP5]], ptr [[TMP4]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 2 // CHECK3-NEXT: store ptr [[B_ADDR]], ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 3 -// CHECK3-NEXT: [[TMP8:%.*]] = load ptr, ptr [[_TMP1]], align 4 +// CHECK3-NEXT: [[TMP8:%.*]] = load ptr, ptr [[_TMP1]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK3-NEXT: store ptr [[TMP8]], ptr [[TMP7]], align 4 // CHECK3-NEXT: call void @_ZZN2SSC1ERiENKUlvE_clEv(ptr nonnull align 4 dereferenceable(16) [[REF_TMP]]) // CHECK3-NEXT: ret void @@ -1053,32 +1053,32 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0:%.*]], ptr [[THIS1]], i32 0, i32 0 // CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 1 -// CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP2]], align 4 +// CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP2]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK3-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4 // CHECK3-NEXT: [[INC:%.*]] = add nsw i32 [[TMP4]], 1 // CHECK3-NEXT: store i32 [[INC]], ptr [[TMP3]], align 4 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 2 -// CHECK3-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP5]], align 4 +// CHECK3-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP5]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK3-NEXT: [[TMP7:%.*]] = load i32, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[DEC:%.*]] = add nsw i32 [[TMP7]], -1 // CHECK3-NEXT: store i32 [[DEC]], ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 3 -// CHECK3-NEXT: [[TMP9:%.*]] = load ptr, ptr [[TMP8]], align 4 +// CHECK3-NEXT: [[TMP9:%.*]] = load ptr, ptr [[TMP8]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK3-NEXT: [[TMP10:%.*]] = load i32, ptr [[TMP9]], align 4 // CHECK3-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP10]], 1 // CHECK3-NEXT: store i32 [[DIV]], ptr [[TMP9]], align 4 // CHECK3-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 1 -// CHECK3-NEXT: [[TMP12:%.*]] = load ptr, ptr [[TMP11]], align 4 +// CHECK3-NEXT: [[TMP12:%.*]] = load ptr, ptr [[TMP11]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK3-NEXT: [[TMP13:%.*]] = load i32, ptr [[TMP12]], align 4 // CHECK3-NEXT: store i32 [[TMP13]], ptr [[A_CASTED]], align 4 // CHECK3-NEXT: [[TMP14:%.*]] = load i32, ptr [[A_CASTED]], align 4 // CHECK3-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 2 -// CHECK3-NEXT: [[TMP16:%.*]] = load ptr, ptr [[TMP15]], align 4 +// CHECK3-NEXT: [[TMP16:%.*]] = load ptr, ptr [[TMP15]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK3-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 // CHECK3-NEXT: store i32 [[TMP17]], ptr [[B_CASTED]], align 4 // CHECK3-NEXT: [[TMP18:%.*]] = load i32, ptr [[B_CASTED]], align 4 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 3 -// CHECK3-NEXT: [[TMP20:%.*]] = load ptr, ptr [[TMP19]], align 4 +// CHECK3-NEXT: [[TMP20:%.*]] = load ptr, ptr [[TMP19]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK3-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 // CHECK3-NEXT: store i32 [[TMP21]], ptr [[C_CASTED]], align 4 // CHECK3-NEXT: [[TMP22:%.*]] = load i32, ptr [[C_CASTED]], align 4 @@ -1106,14 +1106,14 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 // CHECK3-NEXT: store ptr [[A_ADDR]], ptr [[TMP]], align 4 // CHECK3-NEXT: store ptr [[C_ADDR]], ptr [[_TMP1]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK3-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[INC:%.*]] = add nsw i32 [[TMP2]], 1 // CHECK3-NEXT: store i32 [[INC]], ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP3:%.*]] = load i32, ptr [[B_ADDR]], align 4 // CHECK3-NEXT: [[DEC:%.*]] = add nsw i32 [[TMP3]], -1 // CHECK3-NEXT: store i32 [[DEC]], ptr [[B_ADDR]], align 4 -// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[_TMP1]], align 4 +// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[_TMP1]], align 4, !nonnull [[META4]], !align [[META5]] // CHECK3-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4 // CHECK3-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP5]], 1 // CHECK3-NEXT: store i32 [[DIV]], ptr [[TMP4]], align 4 @@ -1252,7 +1252,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK4-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 0 // CHECK4-NEXT: store i8 [[BF_SET]], ptr [[B]], align 4 // CHECK4-NEXT: [[C:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 2 -// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[D_ADDR]], align 4 +// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[D_ADDR]], align 4, !nonnull [[META6:![0-9]+]], !align [[META7:![0-9]+]] // CHECK4-NEXT: store ptr [[TMP0]], ptr [[C]], align 4 // CHECK4-NEXT: [[A3:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 0 // CHECK4-NEXT: store ptr [[A3]], ptr [[A2]], align 4 @@ -1263,22 +1263,22 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK4-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_ASHR]] to i32 // CHECK4-NEXT: store i32 [[BF_CAST]], ptr [[B4]], align 4 // CHECK4-NEXT: [[C8:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 2 -// CHECK4-NEXT: [[TMP1:%.*]] = load ptr, ptr [[C8]], align 4 +// CHECK4-NEXT: [[TMP1:%.*]] = load ptr, ptr [[C8]], align 4, !nonnull [[META6]], !align [[META7]] // CHECK4-NEXT: store ptr [[TMP1]], ptr [[C7]], align 4 // CHECK4-NEXT: [[E9:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 3 // CHECK4-NEXT: store ptr [[E9]], ptr [[E]], align 4 -// CHECK4-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A2]], align 4 +// CHECK4-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A2]], align 4, !nonnull [[META6]], !align [[META7]] // CHECK4-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4 // CHECK4-NEXT: store i32 [[TMP3]], ptr [[A_CASTED]], align 4 // CHECK4-NEXT: [[TMP4:%.*]] = load i32, ptr [[A_CASTED]], align 4 // CHECK4-NEXT: [[TMP5:%.*]] = load i32, ptr [[B4]], align 4 // CHECK4-NEXT: store i32 [[TMP5]], ptr [[B_CASTED]], align 4 // CHECK4-NEXT: [[TMP6:%.*]] = load i32, ptr [[B_CASTED]], align 4 -// CHECK4-NEXT: [[TMP7:%.*]] = load ptr, ptr [[C7]], align 4 +// CHECK4-NEXT: [[TMP7:%.*]] = load ptr, ptr [[C7]], align 4, !nonnull [[META6]], !align [[META7]] // CHECK4-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4 // CHECK4-NEXT: store i32 [[TMP8]], ptr [[C_CASTED]], align 4 // CHECK4-NEXT: [[TMP9:%.*]] = load i32, ptr [[C_CASTED]], align 4 -// CHECK4-NEXT: [[TMP10:%.*]] = load ptr, ptr [[E]], align 4 +// CHECK4-NEXT: [[TMP10:%.*]] = load ptr, ptr [[E]], align 4, !nonnull [[META6]], !align [[META7]] // CHECK4-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 5, ptr @_ZN2SSC2ERi.omp_outlined, ptr [[THIS1]], i32 [[TMP4]], i32 [[TMP6]], i32 [[TMP9]], ptr [[TMP10]]) // CHECK4-NEXT: ret void // @@ -1307,11 +1307,11 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK4-NEXT: store i32 [[C]], ptr [[C_ADDR]], align 4 // CHECK4-NEXT: store ptr [[E]], ptr [[E_ADDR]], align 4 // CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 -// CHECK4-NEXT: [[TMP1:%.*]] = load ptr, ptr [[E_ADDR]], align 4 +// CHECK4-NEXT: [[TMP1:%.*]] = load ptr, ptr [[E_ADDR]], align 4, !nonnull [[META6]], !align [[META7]] // CHECK4-NEXT: store ptr [[A_ADDR]], ptr [[TMP]], align 4 // CHECK4-NEXT: store ptr [[C_ADDR]], ptr [[_TMP1]], align 4 // CHECK4-NEXT: store ptr [[TMP1]], ptr [[_TMP2]], align 4 -// CHECK4-NEXT: [[TMP2:%.*]] = load ptr, ptr [[_TMP2]], align 4 +// CHECK4-NEXT: [[TMP2:%.*]] = load ptr, ptr [[_TMP2]], align 4, !nonnull [[META6]], !align [[META7]] // CHECK4-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[E3]], ptr align 4 [[TMP2]], i32 16, i1 false) // CHECK4-NEXT: store ptr [[E3]], ptr [[_TMP4]], align 4 // CHECK4-NEXT: [[BLOCK_ISA:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, ptr, i32, ptr }>, ptr [[BLOCK]], i32 0, i32 0 @@ -1327,13 +1327,13 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK4-NEXT: [[BLOCK_CAPTURED_THIS_ADDR:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, ptr, i32, ptr }>, ptr [[BLOCK]], i32 0, i32 5 // CHECK4-NEXT: store ptr [[TMP0]], ptr [[BLOCK_CAPTURED_THIS_ADDR]], align 4 // CHECK4-NEXT: [[BLOCK_CAPTURED:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, ptr, i32, ptr }>, ptr [[BLOCK]], i32 0, i32 6 -// CHECK4-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK4-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META6]], !align [[META7]] // CHECK4-NEXT: store ptr [[TMP3]], ptr [[BLOCK_CAPTURED]], align 4 // CHECK4-NEXT: [[BLOCK_CAPTURED5:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, ptr, i32, ptr }>, ptr [[BLOCK]], i32 0, i32 7 // CHECK4-NEXT: [[TMP4:%.*]] = load i32, ptr [[B_ADDR]], align 4 // CHECK4-NEXT: store i32 [[TMP4]], ptr [[BLOCK_CAPTURED5]], align 4 // CHECK4-NEXT: [[BLOCK_CAPTURED6:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, ptr, i32, ptr }>, ptr [[BLOCK]], i32 0, i32 8 -// CHECK4-NEXT: [[TMP5:%.*]] = load ptr, ptr [[_TMP1]], align 4 +// CHECK4-NEXT: [[TMP5:%.*]] = load ptr, ptr [[_TMP1]], align 4, !nonnull [[META6]], !align [[META7]] // CHECK4-NEXT: store ptr [[TMP5]], ptr [[BLOCK_CAPTURED6]], align 4 // CHECK4-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_LITERAL_GENERIC:%.*]], ptr [[BLOCK]], i32 0, i32 3 // CHECK4-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 4 @@ -1354,7 +1354,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK4-NEXT: [[BLOCK_CAPTURED_THIS:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, ptr, i32, ptr }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 5 // CHECK4-NEXT: [[THIS:%.*]] = load ptr, ptr [[BLOCK_CAPTURED_THIS]], align 4 // CHECK4-NEXT: [[BLOCK_CAPTURE_ADDR:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, ptr, i32, ptr }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 6 -// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BLOCK_CAPTURE_ADDR]], align 4 +// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BLOCK_CAPTURE_ADDR]], align 4, !nonnull [[META6]], !align [[META7]] // CHECK4-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4 // CHECK4-NEXT: [[INC:%.*]] = add nsw i32 [[TMP1]], 1 // CHECK4-NEXT: store i32 [[INC]], ptr [[TMP0]], align 4 @@ -1363,12 +1363,12 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK4-NEXT: [[DEC:%.*]] = add nsw i32 [[TMP2]], -1 // CHECK4-NEXT: store i32 [[DEC]], ptr [[BLOCK_CAPTURE_ADDR1]], align 4 // CHECK4-NEXT: [[BLOCK_CAPTURE_ADDR2:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, ptr, i32, ptr }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 8 -// CHECK4-NEXT: [[TMP3:%.*]] = load ptr, ptr [[BLOCK_CAPTURE_ADDR2]], align 4 +// CHECK4-NEXT: [[TMP3:%.*]] = load ptr, ptr [[BLOCK_CAPTURE_ADDR2]], align 4, !nonnull [[META6]], !align [[META7]] // CHECK4-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4 // CHECK4-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP4]], 1 // CHECK4-NEXT: store i32 [[DIV]], ptr [[TMP3]], align 4 // CHECK4-NEXT: [[BLOCK_CAPTURE_ADDR3:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, ptr, i32, ptr }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 6 -// CHECK4-NEXT: [[TMP5:%.*]] = load ptr, ptr [[BLOCK_CAPTURE_ADDR3]], align 4 +// CHECK4-NEXT: [[TMP5:%.*]] = load ptr, ptr [[BLOCK_CAPTURE_ADDR3]], align 4, !nonnull [[META6]], !align [[META7]] // CHECK4-NEXT: [[TMP6:%.*]] = load i32, ptr [[TMP5]], align 4 // CHECK4-NEXT: store i32 [[TMP6]], ptr [[A_CASTED]], align 4 // CHECK4-NEXT: [[TMP7:%.*]] = load i32, ptr [[A_CASTED]], align 4 @@ -1377,7 +1377,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK4-NEXT: store i32 [[TMP8]], ptr [[B_CASTED]], align 4 // CHECK4-NEXT: [[TMP9:%.*]] = load i32, ptr [[B_CASTED]], align 4 // CHECK4-NEXT: [[BLOCK_CAPTURE_ADDR5:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, ptr, i32, ptr }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 8 -// CHECK4-NEXT: [[TMP10:%.*]] = load ptr, ptr [[BLOCK_CAPTURE_ADDR5]], align 4 +// CHECK4-NEXT: [[TMP10:%.*]] = load ptr, ptr [[BLOCK_CAPTURE_ADDR5]], align 4, !nonnull [[META6]], !align [[META7]] // CHECK4-NEXT: [[TMP11:%.*]] = load i32, ptr [[TMP10]], align 4 // CHECK4-NEXT: store i32 [[TMP11]], ptr [[C_CASTED]], align 4 // CHECK4-NEXT: [[TMP12:%.*]] = load i32, ptr [[C_CASTED]], align 4 @@ -1405,14 +1405,14 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 // CHECK4-NEXT: store ptr [[A_ADDR]], ptr [[TMP]], align 4 // CHECK4-NEXT: store ptr [[C_ADDR]], ptr [[_TMP1]], align 4 -// CHECK4-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK4-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META6]], !align [[META7]] // CHECK4-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4 // CHECK4-NEXT: [[INC:%.*]] = add nsw i32 [[TMP2]], 1 // CHECK4-NEXT: store i32 [[INC]], ptr [[TMP1]], align 4 // CHECK4-NEXT: [[TMP3:%.*]] = load i32, ptr [[B_ADDR]], align 4 // CHECK4-NEXT: [[DEC:%.*]] = add nsw i32 [[TMP3]], -1 // CHECK4-NEXT: store i32 [[DEC]], ptr [[B_ADDR]], align 4 -// CHECK4-NEXT: [[TMP4:%.*]] = load ptr, ptr [[_TMP1]], align 4 +// CHECK4-NEXT: [[TMP4:%.*]] = load ptr, ptr [[_TMP1]], align 4, !nonnull [[META6]], !align [[META7]] // CHECK4-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4 // CHECK4-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP5]], 1 // CHECK4-NEXT: store i32 [[DIV]], ptr [[TMP4]], align 4 @@ -1530,9 +1530,9 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK9-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK9-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 // CHECK9-NEXT: store i64 [[SIVAR]], ptr [[SIVAR_ADDR]], align 8 -// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK9-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META3:![0-9]+]], !align [[META4:![0-9]+]] +// CHECK9-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] +// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK9-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VEC1]], ptr align 4 [[TMP0]], i64 8, i1 false) // CHECK9-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR2]], i32 0, i32 0 // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN]], i64 2 @@ -1704,7 +1704,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK9-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 0 // CHECK9-NEXT: store i8 [[BF_SET]], ptr [[B]], align 4 // CHECK9-NEXT: [[C:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 2 -// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[D_ADDR]], align 8 +// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[D_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK9-NEXT: store ptr [[TMP0]], ptr [[C]], align 8 // CHECK9-NEXT: [[A3:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 0 // CHECK9-NEXT: store ptr [[A3]], ptr [[A2]], align 8 @@ -1715,22 +1715,22 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK9-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_ASHR]] to i32 // CHECK9-NEXT: store i32 [[BF_CAST]], ptr [[B4]], align 4 // CHECK9-NEXT: [[C8:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 2 -// CHECK9-NEXT: [[TMP1:%.*]] = load ptr, ptr [[C8]], align 8 +// CHECK9-NEXT: [[TMP1:%.*]] = load ptr, ptr [[C8]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK9-NEXT: store ptr [[TMP1]], ptr [[C7]], align 8 // CHECK9-NEXT: [[E9:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 3 // CHECK9-NEXT: store ptr [[E9]], ptr [[E]], align 8 -// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A2]], align 8 +// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A2]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK9-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4 // CHECK9-NEXT: store i32 [[TMP3]], ptr [[A_CASTED]], align 4 // CHECK9-NEXT: [[TMP4:%.*]] = load i64, ptr [[A_CASTED]], align 8 // CHECK9-NEXT: [[TMP5:%.*]] = load i32, ptr [[B4]], align 4 // CHECK9-NEXT: store i32 [[TMP5]], ptr [[B_CASTED]], align 4 // CHECK9-NEXT: [[TMP6:%.*]] = load i64, ptr [[B_CASTED]], align 8 -// CHECK9-NEXT: [[TMP7:%.*]] = load ptr, ptr [[C7]], align 8 +// CHECK9-NEXT: [[TMP7:%.*]] = load ptr, ptr [[C7]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK9-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4 // CHECK9-NEXT: store i32 [[TMP8]], ptr [[C_CASTED]], align 4 // CHECK9-NEXT: [[TMP9:%.*]] = load i64, ptr [[C_CASTED]], align 8 -// CHECK9-NEXT: [[TMP10:%.*]] = load ptr, ptr [[E]], align 8 +// CHECK9-NEXT: [[TMP10:%.*]] = load ptr, ptr [[E]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 5, ptr @_ZN2SSC2ERi.omp_outlined, ptr [[THIS1]], i64 [[TMP4]], i64 [[TMP6]], i64 [[TMP9]], ptr [[TMP10]]) // CHECK9-NEXT: ret void // @@ -1758,25 +1758,25 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK9-NEXT: store i64 [[C]], ptr [[C_ADDR]], align 8 // CHECK9-NEXT: store ptr [[E]], ptr [[E_ADDR]], align 8 // CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK9-NEXT: [[TMP1:%.*]] = load ptr, ptr [[E_ADDR]], align 8 +// CHECK9-NEXT: [[TMP1:%.*]] = load ptr, ptr [[E_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK9-NEXT: store ptr [[A_ADDR]], ptr [[TMP]], align 8 // CHECK9-NEXT: store ptr [[C_ADDR]], ptr [[_TMP1]], align 8 // CHECK9-NEXT: store ptr [[TMP1]], ptr [[_TMP2]], align 8 -// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[_TMP2]], align 8 +// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[_TMP2]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK9-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[E3]], ptr align 4 [[TMP2]], i64 16, i1 false) // CHECK9-NEXT: store ptr [[E3]], ptr [[_TMP4]], align 8 -// CHECK9-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK9-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK9-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4 // CHECK9-NEXT: [[INC:%.*]] = add nsw i32 [[TMP4]], 1 // CHECK9-NEXT: store i32 [[INC]], ptr [[TMP3]], align 4 // CHECK9-NEXT: [[TMP5:%.*]] = load i32, ptr [[B_ADDR]], align 4 // CHECK9-NEXT: [[DEC:%.*]] = add nsw i32 [[TMP5]], -1 // CHECK9-NEXT: store i32 [[DEC]], ptr [[B_ADDR]], align 4 -// CHECK9-NEXT: [[TMP6:%.*]] = load ptr, ptr [[_TMP1]], align 8 +// CHECK9-NEXT: [[TMP6:%.*]] = load ptr, ptr [[_TMP1]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK9-NEXT: [[TMP7:%.*]] = load i32, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP7]], 1 // CHECK9-NEXT: store i32 [[DIV]], ptr [[TMP6]], align 4 -// CHECK9-NEXT: [[TMP8:%.*]] = load ptr, ptr [[_TMP4]], align 8 +// CHECK9-NEXT: [[TMP8:%.*]] = load ptr, ptr [[_TMP4]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK9-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x i32], ptr [[TMP8]], i64 0, i64 2 // CHECK9-NEXT: store i32 1111, ptr [[ARRAYIDX]], align 4 // CHECK9-NEXT: ret void @@ -1836,7 +1836,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK9-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8 // CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK9-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK9-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP0]], i32 0, i32 0 // CHECK9-NEXT: [[TMP1:%.*]] = load float, ptr [[F2]], align 4 // CHECK9-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -1918,9 +1918,9 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK9-NEXT: store i64 [[T_VAR]], ptr [[T_VAR_ADDR]], align 8 // CHECK9-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK9-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 -// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK9-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] +// CHECK9-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] +// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK9-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 128 [[VEC1]], ptr align 128 [[TMP0]], i64 8, i1 false) // CHECK9-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR2]], i32 0, i32 0 // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN]], i64 2 @@ -2020,7 +2020,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK9-NEXT: store i32 0, ptr [[A]], align 4 // CHECK9-NEXT: [[A3:%.*]] = getelementptr inbounds nuw [[STRUCT_SST]], ptr [[THIS1]], i32 0, i32 0 // CHECK9-NEXT: store ptr [[A3]], ptr [[A2]], align 8 -// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A2]], align 8 +// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A2]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK9-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4 // CHECK9-NEXT: store i32 [[TMP1]], ptr [[A_CASTED]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = load i64, ptr [[A_CASTED]], align 8 @@ -2042,7 +2042,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK9-NEXT: store i64 [[A]], ptr [[A_ADDR]], align 8 // CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK9-NEXT: store ptr [[A_ADDR]], ptr [[TMP]], align 8 -// CHECK9-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK9-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK9-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[INC:%.*]] = add nsw i32 [[TMP2]], 1 // CHECK9-NEXT: store i32 [[INC]], ptr [[TMP1]], align 4 @@ -2076,7 +2076,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK9-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8 // CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK9-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK9-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0]], ptr [[TMP0]], i32 0, i32 0 // CHECK9-NEXT: [[TMP1:%.*]] = load i32, ptr [[F2]], align 4 // CHECK9-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -2145,7 +2145,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK11-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 0 // CHECK11-NEXT: store i8 [[BF_SET]], ptr [[B]], align 4 // CHECK11-NEXT: [[C:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 2 -// CHECK11-NEXT: [[TMP0:%.*]] = load ptr, ptr [[D_ADDR]], align 8 +// CHECK11-NEXT: [[TMP0:%.*]] = load ptr, ptr [[D_ADDR]], align 8, !nonnull [[META3:![0-9]+]], !align [[META4:![0-9]+]] // CHECK11-NEXT: store ptr [[TMP0]], ptr [[C]], align 8 // CHECK11-NEXT: [[A3:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 0 // CHECK11-NEXT: store ptr [[A3]], ptr [[A2]], align 8 @@ -2156,22 +2156,22 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK11-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_ASHR]] to i32 // CHECK11-NEXT: store i32 [[BF_CAST]], ptr [[B4]], align 4 // CHECK11-NEXT: [[C8:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 2 -// CHECK11-NEXT: [[TMP1:%.*]] = load ptr, ptr [[C8]], align 8 +// CHECK11-NEXT: [[TMP1:%.*]] = load ptr, ptr [[C8]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK11-NEXT: store ptr [[TMP1]], ptr [[C7]], align 8 // CHECK11-NEXT: [[E9:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 3 // CHECK11-NEXT: store ptr [[E9]], ptr [[E]], align 8 -// CHECK11-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A2]], align 8 +// CHECK11-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A2]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK11-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4 // CHECK11-NEXT: store i32 [[TMP3]], ptr [[A_CASTED]], align 4 // CHECK11-NEXT: [[TMP4:%.*]] = load i64, ptr [[A_CASTED]], align 8 // CHECK11-NEXT: [[TMP5:%.*]] = load i32, ptr [[B4]], align 4 // CHECK11-NEXT: store i32 [[TMP5]], ptr [[B_CASTED]], align 4 // CHECK11-NEXT: [[TMP6:%.*]] = load i64, ptr [[B_CASTED]], align 8 -// CHECK11-NEXT: [[TMP7:%.*]] = load ptr, ptr [[C7]], align 8 +// CHECK11-NEXT: [[TMP7:%.*]] = load ptr, ptr [[C7]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK11-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4 // CHECK11-NEXT: store i32 [[TMP8]], ptr [[C_CASTED]], align 4 // CHECK11-NEXT: [[TMP9:%.*]] = load i64, ptr [[C_CASTED]], align 8 -// CHECK11-NEXT: [[TMP10:%.*]] = load ptr, ptr [[E]], align 8 +// CHECK11-NEXT: [[TMP10:%.*]] = load ptr, ptr [[E]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK11-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1:[0-9]+]], i32 5, ptr @_ZN2SSC2ERi.omp_outlined, ptr [[THIS1]], i64 [[TMP4]], i64 [[TMP6]], i64 [[TMP9]], ptr [[TMP10]]) // CHECK11-NEXT: ret void // @@ -2200,22 +2200,22 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK11-NEXT: store i64 [[C]], ptr [[C_ADDR]], align 8 // CHECK11-NEXT: store ptr [[E]], ptr [[E_ADDR]], align 8 // CHECK11-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK11-NEXT: [[TMP1:%.*]] = load ptr, ptr [[E_ADDR]], align 8 +// CHECK11-NEXT: [[TMP1:%.*]] = load ptr, ptr [[E_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK11-NEXT: store ptr [[A_ADDR]], ptr [[TMP]], align 8 // CHECK11-NEXT: store ptr [[C_ADDR]], ptr [[_TMP1]], align 8 // CHECK11-NEXT: store ptr [[TMP1]], ptr [[_TMP2]], align 8 -// CHECK11-NEXT: [[TMP2:%.*]] = load ptr, ptr [[_TMP2]], align 8 +// CHECK11-NEXT: [[TMP2:%.*]] = load ptr, ptr [[_TMP2]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK11-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[E3]], ptr align 4 [[TMP2]], i64 16, i1 false) // CHECK11-NEXT: store ptr [[E3]], ptr [[_TMP4]], align 8 // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 0 // CHECK11-NEXT: store ptr [[TMP0]], ptr [[TMP3]], align 8 // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 1 -// CHECK11-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK11-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK11-NEXT: store ptr [[TMP5]], ptr [[TMP4]], align 8 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 2 // CHECK11-NEXT: store ptr [[B_ADDR]], ptr [[TMP6]], align 8 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 3 -// CHECK11-NEXT: [[TMP8:%.*]] = load ptr, ptr [[_TMP1]], align 8 +// CHECK11-NEXT: [[TMP8:%.*]] = load ptr, ptr [[_TMP1]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK11-NEXT: store ptr [[TMP8]], ptr [[TMP7]], align 8 // CHECK11-NEXT: call void @_ZZN2SSC1ERiENKUlvE_clEv(ptr nonnull align 8 dereferenceable(32) [[REF_TMP]]) // CHECK11-NEXT: ret void @@ -2233,32 +2233,32 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK11-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0:%.*]], ptr [[THIS1]], i32 0, i32 0 // CHECK11-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8 // CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 1 -// CHECK11-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP2]], align 8 +// CHECK11-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP2]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK11-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4 // CHECK11-NEXT: [[INC:%.*]] = add nsw i32 [[TMP4]], 1 // CHECK11-NEXT: store i32 [[INC]], ptr [[TMP3]], align 4 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 2 -// CHECK11-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP5]], align 8 +// CHECK11-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP5]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK11-NEXT: [[TMP7:%.*]] = load i32, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[DEC:%.*]] = add nsw i32 [[TMP7]], -1 // CHECK11-NEXT: store i32 [[DEC]], ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 3 -// CHECK11-NEXT: [[TMP9:%.*]] = load ptr, ptr [[TMP8]], align 8 +// CHECK11-NEXT: [[TMP9:%.*]] = load ptr, ptr [[TMP8]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK11-NEXT: [[TMP10:%.*]] = load i32, ptr [[TMP9]], align 4 // CHECK11-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP10]], 1 // CHECK11-NEXT: store i32 [[DIV]], ptr [[TMP9]], align 4 // CHECK11-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 1 -// CHECK11-NEXT: [[TMP12:%.*]] = load ptr, ptr [[TMP11]], align 8 +// CHECK11-NEXT: [[TMP12:%.*]] = load ptr, ptr [[TMP11]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK11-NEXT: [[TMP13:%.*]] = load i32, ptr [[TMP12]], align 4 // CHECK11-NEXT: store i32 [[TMP13]], ptr [[A_CASTED]], align 4 // CHECK11-NEXT: [[TMP14:%.*]] = load i64, ptr [[A_CASTED]], align 8 // CHECK11-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 2 -// CHECK11-NEXT: [[TMP16:%.*]] = load ptr, ptr [[TMP15]], align 8 +// CHECK11-NEXT: [[TMP16:%.*]] = load ptr, ptr [[TMP15]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK11-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 // CHECK11-NEXT: store i32 [[TMP17]], ptr [[B_CASTED]], align 4 // CHECK11-NEXT: [[TMP18:%.*]] = load i64, ptr [[B_CASTED]], align 8 // CHECK11-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 3 -// CHECK11-NEXT: [[TMP20:%.*]] = load ptr, ptr [[TMP19]], align 8 +// CHECK11-NEXT: [[TMP20:%.*]] = load ptr, ptr [[TMP19]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK11-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 // CHECK11-NEXT: store i32 [[TMP21]], ptr [[C_CASTED]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = load i64, ptr [[C_CASTED]], align 8 @@ -2286,14 +2286,14 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK11-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK11-NEXT: store ptr [[A_ADDR]], ptr [[TMP]], align 8 // CHECK11-NEXT: store ptr [[C_ADDR]], ptr [[_TMP1]], align 8 -// CHECK11-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK11-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK11-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4 // CHECK11-NEXT: [[INC:%.*]] = add nsw i32 [[TMP2]], 1 // CHECK11-NEXT: store i32 [[INC]], ptr [[TMP1]], align 4 // CHECK11-NEXT: [[TMP3:%.*]] = load i32, ptr [[B_ADDR]], align 4 // CHECK11-NEXT: [[DEC:%.*]] = add nsw i32 [[TMP3]], -1 // CHECK11-NEXT: store i32 [[DEC]], ptr [[B_ADDR]], align 4 -// CHECK11-NEXT: [[TMP4:%.*]] = load ptr, ptr [[_TMP1]], align 8 +// CHECK11-NEXT: [[TMP4:%.*]] = load ptr, ptr [[_TMP1]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK11-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4 // CHECK11-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP5]], 1 // CHECK11-NEXT: store i32 [[DIV]], ptr [[TMP4]], align 4 @@ -2432,7 +2432,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK12-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 0 // CHECK12-NEXT: store i8 [[BF_SET]], ptr [[B]], align 4 // CHECK12-NEXT: [[C:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 2 -// CHECK12-NEXT: [[TMP0:%.*]] = load ptr, ptr [[D_ADDR]], align 8 +// CHECK12-NEXT: [[TMP0:%.*]] = load ptr, ptr [[D_ADDR]], align 8, !nonnull [[META5:![0-9]+]], !align [[META6:![0-9]+]] // CHECK12-NEXT: store ptr [[TMP0]], ptr [[C]], align 8 // CHECK12-NEXT: [[A3:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 0 // CHECK12-NEXT: store ptr [[A3]], ptr [[A2]], align 8 @@ -2443,22 +2443,22 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK12-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_ASHR]] to i32 // CHECK12-NEXT: store i32 [[BF_CAST]], ptr [[B4]], align 4 // CHECK12-NEXT: [[C8:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 2 -// CHECK12-NEXT: [[TMP1:%.*]] = load ptr, ptr [[C8]], align 8 +// CHECK12-NEXT: [[TMP1:%.*]] = load ptr, ptr [[C8]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK12-NEXT: store ptr [[TMP1]], ptr [[C7]], align 8 // CHECK12-NEXT: [[E9:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 3 // CHECK12-NEXT: store ptr [[E9]], ptr [[E]], align 8 -// CHECK12-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A2]], align 8 +// CHECK12-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A2]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK12-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4 // CHECK12-NEXT: store i32 [[TMP3]], ptr [[A_CASTED]], align 4 // CHECK12-NEXT: [[TMP4:%.*]] = load i64, ptr [[A_CASTED]], align 8 // CHECK12-NEXT: [[TMP5:%.*]] = load i32, ptr [[B4]], align 4 // CHECK12-NEXT: store i32 [[TMP5]], ptr [[B_CASTED]], align 4 // CHECK12-NEXT: [[TMP6:%.*]] = load i64, ptr [[B_CASTED]], align 8 -// CHECK12-NEXT: [[TMP7:%.*]] = load ptr, ptr [[C7]], align 8 +// CHECK12-NEXT: [[TMP7:%.*]] = load ptr, ptr [[C7]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK12-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4 // CHECK12-NEXT: store i32 [[TMP8]], ptr [[C_CASTED]], align 4 // CHECK12-NEXT: [[TMP9:%.*]] = load i64, ptr [[C_CASTED]], align 8 -// CHECK12-NEXT: [[TMP10:%.*]] = load ptr, ptr [[E]], align 8 +// CHECK12-NEXT: [[TMP10:%.*]] = load ptr, ptr [[E]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK12-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 5, ptr @_ZN2SSC2ERi.omp_outlined, ptr [[THIS1]], i64 [[TMP4]], i64 [[TMP6]], i64 [[TMP9]], ptr [[TMP10]]) // CHECK12-NEXT: ret void // @@ -2487,11 +2487,11 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK12-NEXT: store i64 [[C]], ptr [[C_ADDR]], align 8 // CHECK12-NEXT: store ptr [[E]], ptr [[E_ADDR]], align 8 // CHECK12-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK12-NEXT: [[TMP1:%.*]] = load ptr, ptr [[E_ADDR]], align 8 +// CHECK12-NEXT: [[TMP1:%.*]] = load ptr, ptr [[E_ADDR]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK12-NEXT: store ptr [[A_ADDR]], ptr [[TMP]], align 8 // CHECK12-NEXT: store ptr [[C_ADDR]], ptr [[_TMP1]], align 8 // CHECK12-NEXT: store ptr [[TMP1]], ptr [[_TMP2]], align 8 -// CHECK12-NEXT: [[TMP2:%.*]] = load ptr, ptr [[_TMP2]], align 8 +// CHECK12-NEXT: [[TMP2:%.*]] = load ptr, ptr [[_TMP2]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK12-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[E3]], ptr align 4 [[TMP2]], i64 16, i1 false) // CHECK12-NEXT: store ptr [[E3]], ptr [[_TMP4]], align 8 // CHECK12-NEXT: [[BLOCK_ISA:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, ptr, ptr, i32 }>, ptr [[BLOCK]], i32 0, i32 0 @@ -2507,13 +2507,13 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK12-NEXT: [[BLOCK_CAPTURED_THIS_ADDR:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, ptr, ptr, i32 }>, ptr [[BLOCK]], i32 0, i32 5 // CHECK12-NEXT: store ptr [[TMP0]], ptr [[BLOCK_CAPTURED_THIS_ADDR]], align 8 // CHECK12-NEXT: [[BLOCK_CAPTURED:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, ptr, ptr, i32 }>, ptr [[BLOCK]], i32 0, i32 6 -// CHECK12-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK12-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK12-NEXT: store ptr [[TMP3]], ptr [[BLOCK_CAPTURED]], align 8 // CHECK12-NEXT: [[BLOCK_CAPTURED5:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, ptr, ptr, i32 }>, ptr [[BLOCK]], i32 0, i32 8 // CHECK12-NEXT: [[TMP4:%.*]] = load i32, ptr [[B_ADDR]], align 4 // CHECK12-NEXT: store i32 [[TMP4]], ptr [[BLOCK_CAPTURED5]], align 8 // CHECK12-NEXT: [[BLOCK_CAPTURED6:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, ptr, ptr, i32 }>, ptr [[BLOCK]], i32 0, i32 7 -// CHECK12-NEXT: [[TMP5:%.*]] = load ptr, ptr [[_TMP1]], align 8 +// CHECK12-NEXT: [[TMP5:%.*]] = load ptr, ptr [[_TMP1]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK12-NEXT: store ptr [[TMP5]], ptr [[BLOCK_CAPTURED6]], align 8 // CHECK12-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_LITERAL_GENERIC:%.*]], ptr [[BLOCK]], i32 0, i32 3 // CHECK12-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 @@ -2534,7 +2534,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK12-NEXT: [[BLOCK_CAPTURED_THIS:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, ptr, ptr, i32 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 5 // CHECK12-NEXT: [[THIS:%.*]] = load ptr, ptr [[BLOCK_CAPTURED_THIS]], align 8 // CHECK12-NEXT: [[BLOCK_CAPTURE_ADDR:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, ptr, ptr, i32 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 6 -// CHECK12-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BLOCK_CAPTURE_ADDR]], align 8 +// CHECK12-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BLOCK_CAPTURE_ADDR]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK12-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4 // CHECK12-NEXT: [[INC:%.*]] = add nsw i32 [[TMP1]], 1 // CHECK12-NEXT: store i32 [[INC]], ptr [[TMP0]], align 4 @@ -2543,12 +2543,12 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK12-NEXT: [[DEC:%.*]] = add nsw i32 [[TMP2]], -1 // CHECK12-NEXT: store i32 [[DEC]], ptr [[BLOCK_CAPTURE_ADDR1]], align 8 // CHECK12-NEXT: [[BLOCK_CAPTURE_ADDR2:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, ptr, ptr, i32 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 7 -// CHECK12-NEXT: [[TMP3:%.*]] = load ptr, ptr [[BLOCK_CAPTURE_ADDR2]], align 8 +// CHECK12-NEXT: [[TMP3:%.*]] = load ptr, ptr [[BLOCK_CAPTURE_ADDR2]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK12-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4 // CHECK12-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP4]], 1 // CHECK12-NEXT: store i32 [[DIV]], ptr [[TMP3]], align 4 // CHECK12-NEXT: [[BLOCK_CAPTURE_ADDR3:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, ptr, ptr, i32 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 6 -// CHECK12-NEXT: [[TMP5:%.*]] = load ptr, ptr [[BLOCK_CAPTURE_ADDR3]], align 8 +// CHECK12-NEXT: [[TMP5:%.*]] = load ptr, ptr [[BLOCK_CAPTURE_ADDR3]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK12-NEXT: [[TMP6:%.*]] = load i32, ptr [[TMP5]], align 4 // CHECK12-NEXT: store i32 [[TMP6]], ptr [[A_CASTED]], align 4 // CHECK12-NEXT: [[TMP7:%.*]] = load i64, ptr [[A_CASTED]], align 8 @@ -2557,7 +2557,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK12-NEXT: store i32 [[TMP8]], ptr [[B_CASTED]], align 4 // CHECK12-NEXT: [[TMP9:%.*]] = load i64, ptr [[B_CASTED]], align 8 // CHECK12-NEXT: [[BLOCK_CAPTURE_ADDR5:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr, ptr, ptr, i32 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 7 -// CHECK12-NEXT: [[TMP10:%.*]] = load ptr, ptr [[BLOCK_CAPTURE_ADDR5]], align 8 +// CHECK12-NEXT: [[TMP10:%.*]] = load ptr, ptr [[BLOCK_CAPTURE_ADDR5]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK12-NEXT: [[TMP11:%.*]] = load i32, ptr [[TMP10]], align 4 // CHECK12-NEXT: store i32 [[TMP11]], ptr [[C_CASTED]], align 4 // CHECK12-NEXT: [[TMP12:%.*]] = load i64, ptr [[C_CASTED]], align 8 @@ -2585,14 +2585,14 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK12-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK12-NEXT: store ptr [[A_ADDR]], ptr [[TMP]], align 8 // CHECK12-NEXT: store ptr [[C_ADDR]], ptr [[_TMP1]], align 8 -// CHECK12-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK12-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK12-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4 // CHECK12-NEXT: [[INC:%.*]] = add nsw i32 [[TMP2]], 1 // CHECK12-NEXT: store i32 [[INC]], ptr [[TMP1]], align 4 // CHECK12-NEXT: [[TMP3:%.*]] = load i32, ptr [[B_ADDR]], align 4 // CHECK12-NEXT: [[DEC:%.*]] = add nsw i32 [[TMP3]], -1 // CHECK12-NEXT: store i32 [[DEC]], ptr [[B_ADDR]], align 4 -// CHECK12-NEXT: [[TMP4:%.*]] = load ptr, ptr [[_TMP1]], align 8 +// CHECK12-NEXT: [[TMP4:%.*]] = load ptr, ptr [[_TMP1]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK12-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4 // CHECK12-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP5]], 1 // CHECK12-NEXT: store i32 [[DIV]], ptr [[TMP4]], align 4 @@ -2660,11 +2660,11 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK17-NEXT: store i64 [[VLA2]], ptr [[VLA_ADDR3]], align 8 // CHECK17-NEXT: store i64 [[VLA4]], ptr [[VLA_ADDR5]], align 8 // CHECK17-NEXT: store ptr [[VLA26]], ptr [[VLA2_ADDR]], align 8 -// CHECK17-NEXT: [[TMP0:%.*]] = load ptr, ptr [[N_ADDR]], align 8 +// CHECK17-NEXT: [[TMP0:%.*]] = load ptr, ptr [[N_ADDR]], align 8, !nonnull [[META3:![0-9]+]], !align [[META4:![0-9]+]] // CHECK17-NEXT: [[TMP1:%.*]] = load i64, ptr [[VLA_ADDR]], align 8 // CHECK17-NEXT: [[TMP2:%.*]] = load i64, ptr [[VLA_ADDR3]], align 8 // CHECK17-NEXT: [[TMP3:%.*]] = load i64, ptr [[VLA_ADDR5]], align 8 -// CHECK17-NEXT: [[TMP4:%.*]] = load ptr, ptr [[VLA2_ADDR]], align 8 +// CHECK17-NEXT: [[TMP4:%.*]] = load ptr, ptr [[VLA2_ADDR]], align 8, !nonnull [[META3]], !align [[META5:![0-9]+]] // CHECK17-NEXT: [[TMP5:%.*]] = call ptr @llvm.stacksave.p0() // CHECK17-NEXT: store ptr [[TMP5]], ptr [[SAVED_STACK]], align 8 // CHECK17-NEXT: [[TMP6:%.*]] = mul nuw i64 [[TMP2]], [[TMP3]] @@ -2751,8 +2751,8 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK17-NEXT: [[TMP1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK17-NEXT: [[TMP2:%.*]] = load i64, ptr [[VLA_ADDR3]], align 8 // CHECK17-NEXT: [[TMP3:%.*]] = load i64, ptr [[VLA_ADDR5]], align 8 -// CHECK17-NEXT: [[TMP4:%.*]] = load ptr, ptr [[VLA2_ADDR]], align 8 -// CHECK17-NEXT: [[TMP5:%.*]] = load ptr, ptr [[N_ADDR]], align 8 +// CHECK17-NEXT: [[TMP4:%.*]] = load ptr, ptr [[VLA2_ADDR]], align 8, !nonnull [[META3]], !align [[META5]] +// CHECK17-NEXT: [[TMP5:%.*]] = load ptr, ptr [[N_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK17-NEXT: [[TMP6:%.*]] = mul nuw i64 [[TMP2]], [[TMP3]] // CHECK17-NEXT: [[TMP7:%.*]] = mul nuw i64 [[TMP6]], 8 // CHECK17-NEXT: [[TMP8:%.*]] = add nuw i64 [[TMP7]], 127 diff --git a/clang/test/OpenMP/sections_firstprivate_codegen.cpp b/clang/test/OpenMP/sections_firstprivate_codegen.cpp index 7c6d1839fb10e..32c5826e6f75d 100644 --- a/clang/test/OpenMP/sections_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/sections_firstprivate_codegen.cpp @@ -448,7 +448,7 @@ int main() { // CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8 // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !nonnull [[META3:![0-9]+]], !align [[META4:![0-9]+]] // CHECK1-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP0]], i32 0, i32 0 // CHECK1-NEXT: [[TMP1:%.*]] = load float, ptr [[F2]], align 4 // CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -517,10 +517,10 @@ int main() { // CHECK1-NEXT: store ptr [[VEC]], ptr [[VEC_ADDR]], align 8 // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[T_VAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[T_VAR_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] +// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_SECTIONS_LB_]], align 4 // CHECK1-NEXT: store i32 1, ptr [[DOTOMP_SECTIONS_UB_]], align 4 // CHECK1-NEXT: store i32 1, ptr [[DOTOMP_SECTIONS_ST_]], align 4 @@ -668,7 +668,7 @@ int main() { // CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8 // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK1-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0]], ptr [[TMP0]], i32 0, i32 0 // CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[F2]], align 4 // CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -996,7 +996,7 @@ int main() { // CHECK4-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK4-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8 // CHECK4-NEXT: store ptr [[SIVAR]], ptr [[SIVAR_ADDR]], align 8 -// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[SIVAR_ADDR]], align 8 +// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[SIVAR_ADDR]], align 8, !nonnull [[META3:![0-9]+]], !align [[META4:![0-9]+]] // CHECK4-NEXT: store i32 0, ptr [[DOTOMP_SECTIONS_LB_]], align 4 // CHECK4-NEXT: store i32 1, ptr [[DOTOMP_SECTIONS_UB_]], align 4 // CHECK4-NEXT: store i32 1, ptr [[DOTOMP_SECTIONS_ST_]], align 4 diff --git a/clang/test/OpenMP/single_firstprivate_codegen.cpp b/clang/test/OpenMP/single_firstprivate_codegen.cpp index 27cd220adf225..31ea1ca4952fc 100644 --- a/clang/test/OpenMP/single_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/single_firstprivate_codegen.cpp @@ -403,7 +403,7 @@ int main() { // CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8 // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !nonnull [[META3:![0-9]+]], !align [[META4:![0-9]+]] // CHECK1-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP0]], i32 0, i32 0 // CHECK1-NEXT: [[TMP1:%.*]] = load float, ptr [[F2]], align 4 // CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -467,10 +467,10 @@ int main() { // CHECK1-NEXT: store ptr [[VEC]], ptr [[VEC_ADDR]], align 8 // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[T_VAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[T_VAR_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] +// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = call i32 @__kmpc_single(ptr @[[GLOB1]], i32 [[TMP5]]) @@ -585,7 +585,7 @@ int main() { // CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8 // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !nonnull [[META3]], !align [[META4]] // CHECK1-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0]], ptr [[TMP0]], i32 0, i32 0 // CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[F2]], align 4 // CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -908,7 +908,7 @@ int main() { // CHECK4-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK4-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8 // CHECK4-NEXT: store ptr [[SIVAR]], ptr [[SIVAR_ADDR]], align 8 -// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[SIVAR_ADDR]], align 8 +// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[SIVAR_ADDR]], align 8, !nonnull [[META3:![0-9]+]], !align [[META4:![0-9]+]] // CHECK4-NEXT: [[TMP1:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK4-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4 // CHECK4-NEXT: [[TMP3:%.*]] = call i32 @__kmpc_single(ptr @[[GLOB1]], i32 [[TMP2]]) diff --git a/clang/test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp index aa50d8fb3aabd..a171827a18646 100644 --- a/clang/test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp @@ -354,9 +354,9 @@ int main() { // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 // CHECK1-NEXT: store i64 [[SIVAR]], ptr [[SIVAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META7:![0-9]+]], !align [[META8:![0-9]+]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK1-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK1-NEXT: [[TMP4:%.*]] = load i64, ptr [[T_VAR_CASTED]], align 8 @@ -396,9 +396,9 @@ int main() { // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 // CHECK1-NEXT: store i64 [[SIVAR]], ptr [[SIVAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK1-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 // CHECK1-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4 @@ -550,12 +550,12 @@ int main() { // CHECK1-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[S_ARR]], i64 1 // CHECK1-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], i32 noundef signext 2) // CHECK1-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: store ptr [[TMP0]], ptr [[TMP]], align 8 // CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[T_VAR]], align 4 // CHECK1-NEXT: store i32 [[TMP1]], ptr [[T_VAR_CASTED]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = load i64, ptr [[T_VAR_CASTED]], align 8 -// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: store ptr [[VEC]], ptr [[TMP4]], align 8 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 @@ -655,7 +655,7 @@ int main() { // CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8 // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP0]], i32 0, i32 0 // CHECK1-NEXT: [[TMP1:%.*]] = load float, ptr [[F2]], align 4 // CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -711,14 +711,14 @@ int main() { // CHECK1-NEXT: store i64 [[T_VAR]], ptr [[T_VAR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 8 // CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK1-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK1-NEXT: [[TMP4:%.*]] = load i64, ptr [[T_VAR_CASTED]], align 8 -// CHECK1-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK1-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB2]], i32 4, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l56.omp_outlined, ptr [[TMP0]], i64 [[TMP4]], ptr [[TMP1]], ptr [[TMP5]]) // CHECK1-NEXT: ret void // @@ -752,9 +752,9 @@ int main() { // CHECK1-NEXT: store i64 [[T_VAR]], ptr [[T_VAR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 8 // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK1-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 @@ -776,7 +776,7 @@ int main() { // CHECK1-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP3]] // CHECK1-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE4]], label [[OMP_ARRAYCPY_BODY]] // CHECK1: omp.arraycpy.done4: -// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: call void @_ZN2StC1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) // CHECK1-NEXT: call void @_ZN1SIiEC1ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP4]], ptr noundef [[AGG_TMP6]]) // CHECK1-NEXT: call void @_ZN2StD1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) #[[ATTR2]] @@ -815,7 +815,7 @@ int main() { // CHECK1-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP14]] to i64 // CHECK1-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i32], ptr [[VEC2]], i64 0, i64 [[IDXPROM]] // CHECK1-NEXT: store i32 [[TMP13]], ptr [[ARRAYIDX]], align 4 -// CHECK1-NEXT: [[TMP15:%.*]] = load ptr, ptr [[_TMP7]], align 8 +// CHECK1-NEXT: [[TMP15:%.*]] = load ptr, ptr [[_TMP7]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[I]], align 4 // CHECK1-NEXT: [[IDXPROM9:%.*]] = sext i32 [[TMP16]] to i64 // CHECK1-NEXT: [[ARRAYIDX10:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR3]], i64 0, i64 [[IDXPROM9]] @@ -912,7 +912,7 @@ int main() { // CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8 // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0]], ptr [[TMP0]], i32 0, i32 0 // CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[F2]], align 4 // CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -1155,9 +1155,9 @@ int main() { // CHECK3-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 // CHECK3-NEXT: store i32 [[SIVAR]], ptr [[SIVAR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META8:![0-9]+]], !align [[META9:![0-9]+]] +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK3-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK3-NEXT: [[TMP4:%.*]] = load i32, ptr [[T_VAR_CASTED]], align 4 @@ -1197,9 +1197,9 @@ int main() { // CHECK3-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 // CHECK3-NEXT: store i32 [[SIVAR]], ptr [[SIVAR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK3-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 // CHECK3-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4 @@ -1349,12 +1349,12 @@ int main() { // CHECK3-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[S_ARR]], i32 1 // CHECK3-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], i32 noundef 2) // CHECK3-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: store ptr [[TMP0]], ptr [[TMP]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = load i32, ptr [[T_VAR]], align 4 // CHECK3-NEXT: store i32 [[TMP1]], ptr [[T_VAR_CASTED]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = load i32, ptr [[T_VAR_CASTED]], align 4 -// CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: store ptr [[VEC]], ptr [[TMP4]], align 4 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 @@ -1454,7 +1454,7 @@ int main() { // CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4 // CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 // CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP0]], i32 0, i32 0 // CHECK3-NEXT: [[TMP1:%.*]] = load float, ptr [[F2]], align 4 // CHECK3-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -1510,14 +1510,14 @@ int main() { // CHECK3-NEXT: store i32 [[T_VAR]], ptr [[T_VAR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 4 // CHECK3-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK3-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK3-NEXT: [[TMP4:%.*]] = load i32, ptr [[T_VAR_CASTED]], align 4 -// CHECK3-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK3-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB2]], i32 4, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l56.omp_outlined, ptr [[TMP0]], i32 [[TMP4]], ptr [[TMP1]], ptr [[TMP5]]) // CHECK3-NEXT: ret void // @@ -1551,9 +1551,9 @@ int main() { // CHECK3-NEXT: store i32 [[T_VAR]], ptr [[T_VAR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 4 // CHECK3-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK3-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 @@ -1575,7 +1575,7 @@ int main() { // CHECK3-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP3]] // CHECK3-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE4]], label [[OMP_ARRAYCPY_BODY]] // CHECK3: omp.arraycpy.done4: -// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: call void @_ZN2StC1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) // CHECK3-NEXT: call void @_ZN1SIiEC1ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP4]], ptr noundef [[AGG_TMP6]]) // CHECK3-NEXT: call void @_ZN2StD1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) #[[ATTR2]] @@ -1613,7 +1613,7 @@ int main() { // CHECK3-NEXT: [[TMP14:%.*]] = load i32, ptr [[I]], align 4 // CHECK3-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i32], ptr [[VEC2]], i32 0, i32 [[TMP14]] // CHECK3-NEXT: store i32 [[TMP13]], ptr [[ARRAYIDX]], align 4 -// CHECK3-NEXT: [[TMP15:%.*]] = load ptr, ptr [[_TMP7]], align 4 +// CHECK3-NEXT: [[TMP15:%.*]] = load ptr, ptr [[_TMP7]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: [[TMP16:%.*]] = load i32, ptr [[I]], align 4 // CHECK3-NEXT: [[ARRAYIDX9:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR3]], i32 0, i32 [[TMP16]] // CHECK3-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[ARRAYIDX9]], ptr align 4 [[TMP15]], i32 4, i1 false) @@ -1709,7 +1709,7 @@ int main() { // CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4 // CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 // CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0]], ptr [[TMP0]], i32 0, i32 0 // CHECK3-NEXT: [[TMP1:%.*]] = load i32, ptr [[F2]], align 4 // CHECK3-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -1877,7 +1877,7 @@ int main() { // CHECK9-NEXT: [[TMP0:%.*]] = load i32, ptr [[G_ADDR]], align 4 // CHECK9-NEXT: store i32 [[TMP0]], ptr [[G_CASTED]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = load i64, ptr [[G_CASTED]], align 8 -// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META5:![0-9]+]], !align [[META6:![0-9]+]] // CHECK9-NEXT: [[TMP3:%.*]] = load volatile i32, ptr [[TMP2]], align 4 // CHECK9-NEXT: store i32 [[TMP3]], ptr [[G1_CASTED]], align 4 // CHECK9-NEXT: [[TMP4:%.*]] = load i64, ptr [[G1_CASTED]], align 8 @@ -1943,13 +1943,13 @@ int main() { // CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]] // CHECK9-NEXT: store i32 [[ADD]], ptr [[I]], align 4 // CHECK9-NEXT: store i32 1, ptr [[G_ADDR]], align 4 -// CHECK9-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK9-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK9-NEXT: store volatile i32 1, ptr [[TMP8]], align 4 // CHECK9-NEXT: store i32 2, ptr [[SIVAR_ADDR]], align 4 // CHECK9-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 0 // CHECK9-NEXT: store ptr [[G_ADDR]], ptr [[TMP9]], align 8 // CHECK9-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 1 -// CHECK9-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK9-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK9-NEXT: store ptr [[TMP11]], ptr [[TMP10]], align 8 // CHECK9-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 2 // CHECK9-NEXT: store ptr [[SIVAR_ADDR]], ptr [[TMP12]], align 8 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_codegen.cpp index 78e40e54671ac..678770520f677 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_codegen.cpp @@ -415,9 +415,9 @@ int main() { // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 // CHECK1-NEXT: store i64 [[SIVAR]], ptr [[SIVAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META7:![0-9]+]], !align [[META8:![0-9]+]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK1-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK1-NEXT: [[TMP4:%.*]] = load i64, ptr [[T_VAR_CASTED]], align 8 @@ -459,9 +459,9 @@ int main() { // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 // CHECK1-NEXT: store i64 [[SIVAR]], ptr [[SIVAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_COMB_LB]], align 4 // CHECK1-NEXT: store i32 1, ptr [[DOTOMP_COMB_UB]], align 4 // CHECK1-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4 @@ -616,9 +616,9 @@ int main() { // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 // CHECK1-NEXT: store i64 [[SIVAR]], ptr [[SIVAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK1-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 // CHECK1-NEXT: [[TMP3:%.*]] = load i64, ptr [[DOTPREVIOUS_LB__ADDR]], align 8 @@ -741,12 +741,12 @@ int main() { // CHECK1-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[S_ARR]], i64 1 // CHECK1-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], i32 noundef signext 2) // CHECK1-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: store ptr [[TMP0]], ptr [[TMP]], align 8 // CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[T_VAR]], align 4 // CHECK1-NEXT: store i32 [[TMP1]], ptr [[T_VAR_CASTED]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = load i64, ptr [[T_VAR_CASTED]], align 8 -// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: store ptr [[VEC]], ptr [[TMP4]], align 8 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 @@ -846,7 +846,7 @@ int main() { // CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8 // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP0]], i32 0, i32 0 // CHECK1-NEXT: [[TMP1:%.*]] = load float, ptr [[F2]], align 4 // CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -902,14 +902,14 @@ int main() { // CHECK1-NEXT: store i64 [[T_VAR]], ptr [[T_VAR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 8 // CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK1-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK1-NEXT: [[TMP4:%.*]] = load i64, ptr [[T_VAR_CASTED]], align 8 -// CHECK1-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK1-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB3]], i32 4, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l81.omp_outlined, ptr [[TMP0]], i64 [[TMP4]], ptr [[TMP1]], ptr [[TMP5]]) // CHECK1-NEXT: ret void // @@ -944,9 +944,9 @@ int main() { // CHECK1-NEXT: store i64 [[T_VAR]], ptr [[T_VAR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 8 // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_COMB_LB]], align 4 // CHECK1-NEXT: store i32 1, ptr [[DOTOMP_COMB_UB]], align 4 @@ -968,7 +968,7 @@ int main() { // CHECK1-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP3]] // CHECK1-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE4]], label [[OMP_ARRAYCPY_BODY]] // CHECK1: omp.arraycpy.done4: -// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: call void @_ZN2StC1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) // CHECK1-NEXT: call void @_ZN1SIiEC1ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP4]], ptr noundef [[AGG_TMP6]]) // CHECK1-NEXT: call void @_ZN2StD1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) #[[ATTR2]] @@ -1005,7 +1005,7 @@ int main() { // CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK1-NEXT: store i32 [[TMP16]], ptr [[T_VAR_CASTED]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = load i64, ptr [[T_VAR_CASTED]], align 8 -// CHECK1-NEXT: [[TMP18:%.*]] = load ptr, ptr [[_TMP7]], align 8 +// CHECK1-NEXT: [[TMP18:%.*]] = load ptr, ptr [[_TMP7]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB3]], i32 6, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l81.omp_outlined.omp_outlined, i64 [[TMP13]], i64 [[TMP15]], ptr [[VEC2]], i64 [[TMP17]], ptr [[S_ARR3]], ptr [[TMP18]]) // CHECK1-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] // CHECK1: omp.inner.for.inc: @@ -1082,9 +1082,9 @@ int main() { // CHECK1-NEXT: store i64 [[T_VAR]], ptr [[T_VAR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 8 // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK1-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 @@ -1112,7 +1112,7 @@ int main() { // CHECK1-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP5]] // CHECK1-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE5]], label [[OMP_ARRAYCPY_BODY]] // CHECK1: omp.arraycpy.done5: -// CHECK1-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK1-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: call void @_ZN2StC1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP7]]) // CHECK1-NEXT: call void @_ZN1SIiEC1ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[VAR6]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP6]], ptr noundef [[AGG_TMP7]]) // CHECK1-NEXT: call void @_ZN2StD1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP7]]) #[[ATTR2]] @@ -1151,7 +1151,7 @@ int main() { // CHECK1-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP16]] to i64 // CHECK1-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i32], ptr [[VEC3]], i64 0, i64 [[IDXPROM]] // CHECK1-NEXT: store i32 [[TMP15]], ptr [[ARRAYIDX]], align 4 -// CHECK1-NEXT: [[TMP17:%.*]] = load ptr, ptr [[_TMP8]], align 8 +// CHECK1-NEXT: [[TMP17:%.*]] = load ptr, ptr [[_TMP8]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: [[TMP18:%.*]] = load i32, ptr [[I]], align 4 // CHECK1-NEXT: [[IDXPROM10:%.*]] = sext i32 [[TMP18]] to i64 // CHECK1-NEXT: [[ARRAYIDX11:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR4]], i64 0, i64 [[IDXPROM10]] @@ -1233,7 +1233,7 @@ int main() { // CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8 // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0]], ptr [[TMP0]], i32 0, i32 0 // CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[F2]], align 4 // CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -1476,9 +1476,9 @@ int main() { // CHECK3-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 // CHECK3-NEXT: store i32 [[SIVAR]], ptr [[SIVAR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META8:![0-9]+]], !align [[META9:![0-9]+]] +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK3-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK3-NEXT: [[TMP4:%.*]] = load i32, ptr [[T_VAR_CASTED]], align 4 @@ -1520,9 +1520,9 @@ int main() { // CHECK3-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 // CHECK3-NEXT: store i32 [[SIVAR]], ptr [[SIVAR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: store i32 0, ptr [[DOTOMP_COMB_LB]], align 4 // CHECK3-NEXT: store i32 1, ptr [[DOTOMP_COMB_UB]], align 4 // CHECK3-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4 @@ -1675,9 +1675,9 @@ int main() { // CHECK3-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 // CHECK3-NEXT: store i32 [[SIVAR]], ptr [[SIVAR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK3-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 // CHECK3-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTPREVIOUS_LB__ADDR]], align 4 @@ -1796,12 +1796,12 @@ int main() { // CHECK3-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[S_ARR]], i32 1 // CHECK3-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], i32 noundef 2) // CHECK3-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: store ptr [[TMP0]], ptr [[TMP]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = load i32, ptr [[T_VAR]], align 4 // CHECK3-NEXT: store i32 [[TMP1]], ptr [[T_VAR_CASTED]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = load i32, ptr [[T_VAR_CASTED]], align 4 -// CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: store ptr [[VEC]], ptr [[TMP4]], align 4 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 @@ -1901,7 +1901,7 @@ int main() { // CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4 // CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 // CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP0]], i32 0, i32 0 // CHECK3-NEXT: [[TMP1:%.*]] = load float, ptr [[F2]], align 4 // CHECK3-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -1957,14 +1957,14 @@ int main() { // CHECK3-NEXT: store i32 [[T_VAR]], ptr [[T_VAR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 4 // CHECK3-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK3-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK3-NEXT: [[TMP4:%.*]] = load i32, ptr [[T_VAR_CASTED]], align 4 -// CHECK3-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK3-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB3]], i32 4, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l81.omp_outlined, ptr [[TMP0]], i32 [[TMP4]], ptr [[TMP1]], ptr [[TMP5]]) // CHECK3-NEXT: ret void // @@ -1999,9 +1999,9 @@ int main() { // CHECK3-NEXT: store i32 [[T_VAR]], ptr [[T_VAR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 4 // CHECK3-NEXT: store i32 0, ptr [[DOTOMP_COMB_LB]], align 4 // CHECK3-NEXT: store i32 1, ptr [[DOTOMP_COMB_UB]], align 4 @@ -2023,7 +2023,7 @@ int main() { // CHECK3-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP3]] // CHECK3-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE4]], label [[OMP_ARRAYCPY_BODY]] // CHECK3: omp.arraycpy.done4: -// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: call void @_ZN2StC1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) // CHECK3-NEXT: call void @_ZN1SIiEC1ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP4]], ptr noundef [[AGG_TMP6]]) // CHECK3-NEXT: call void @_ZN2StD1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) #[[ATTR2]] @@ -2058,7 +2058,7 @@ int main() { // CHECK3-NEXT: [[TMP14:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK3-NEXT: store i32 [[TMP14]], ptr [[T_VAR_CASTED]], align 4 // CHECK3-NEXT: [[TMP15:%.*]] = load i32, ptr [[T_VAR_CASTED]], align 4 -// CHECK3-NEXT: [[TMP16:%.*]] = load ptr, ptr [[_TMP7]], align 4 +// CHECK3-NEXT: [[TMP16:%.*]] = load ptr, ptr [[_TMP7]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB3]], i32 6, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l81.omp_outlined.omp_outlined, i32 [[TMP12]], i32 [[TMP13]], ptr [[VEC2]], i32 [[TMP15]], ptr [[S_ARR3]], ptr [[TMP16]]) // CHECK3-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] // CHECK3: omp.inner.for.inc: @@ -2135,9 +2135,9 @@ int main() { // CHECK3-NEXT: store i32 [[T_VAR]], ptr [[T_VAR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 4 // CHECK3-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK3-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 @@ -2163,7 +2163,7 @@ int main() { // CHECK3-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP5]] // CHECK3-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE4]], label [[OMP_ARRAYCPY_BODY]] // CHECK3: omp.arraycpy.done4: -// CHECK3-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK3-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: call void @_ZN2StC1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) // CHECK3-NEXT: call void @_ZN1SIiEC1ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP6]], ptr noundef [[AGG_TMP6]]) // CHECK3-NEXT: call void @_ZN2StD1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) #[[ATTR2]] @@ -2201,7 +2201,7 @@ int main() { // CHECK3-NEXT: [[TMP16:%.*]] = load i32, ptr [[I]], align 4 // CHECK3-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i32], ptr [[VEC2]], i32 0, i32 [[TMP16]] // CHECK3-NEXT: store i32 [[TMP15]], ptr [[ARRAYIDX]], align 4 -// CHECK3-NEXT: [[TMP17:%.*]] = load ptr, ptr [[_TMP7]], align 4 +// CHECK3-NEXT: [[TMP17:%.*]] = load ptr, ptr [[_TMP7]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: [[TMP18:%.*]] = load i32, ptr [[I]], align 4 // CHECK3-NEXT: [[ARRAYIDX9:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR3]], i32 0, i32 [[TMP18]] // CHECK3-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[ARRAYIDX9]], ptr align 4 [[TMP17]], i32 4, i1 false) @@ -2282,7 +2282,7 @@ int main() { // CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4 // CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 // CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0]], ptr [[TMP0]], i32 0, i32 0 // CHECK3-NEXT: [[TMP1:%.*]] = load i32, ptr [[F2]], align 4 // CHECK3-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -2450,7 +2450,7 @@ int main() { // CHECK5-NEXT: [[TMP0:%.*]] = load i32, ptr [[G_ADDR]], align 4 // CHECK5-NEXT: store i32 [[TMP0]], ptr [[G_CASTED]], align 4 // CHECK5-NEXT: [[TMP1:%.*]] = load i64, ptr [[G_CASTED]], align 8 -// CHECK5-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK5-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META5:![0-9]+]], !align [[META6:![0-9]+]] // CHECK5-NEXT: [[TMP3:%.*]] = load volatile i32, ptr [[TMP2]], align 4 // CHECK5-NEXT: store i32 [[TMP3]], ptr [[G1_CASTED]], align 4 // CHECK5-NEXT: [[TMP4:%.*]] = load i64, ptr [[G1_CASTED]], align 8 @@ -2520,7 +2520,7 @@ int main() { // CHECK5-NEXT: [[TMP11:%.*]] = load i32, ptr [[G_ADDR]], align 4 // CHECK5-NEXT: store i32 [[TMP11]], ptr [[G_CASTED]], align 4 // CHECK5-NEXT: [[TMP12:%.*]] = load i64, ptr [[G_CASTED]], align 8 -// CHECK5-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK5-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK5-NEXT: [[TMP14:%.*]] = load volatile i32, ptr [[TMP13]], align 4 // CHECK5-NEXT: store i32 [[TMP14]], ptr [[G1_CASTED]], align 4 // CHECK5-NEXT: [[TMP15:%.*]] = load i64, ptr [[G1_CASTED]], align 8 @@ -2607,13 +2607,13 @@ int main() { // CHECK5-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]] // CHECK5-NEXT: store i32 [[ADD]], ptr [[I]], align 4 // CHECK5-NEXT: store i32 1, ptr [[G_ADDR]], align 4 -// CHECK5-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK5-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK5-NEXT: store volatile i32 1, ptr [[TMP10]], align 4 // CHECK5-NEXT: store i32 2, ptr [[SIVAR_ADDR]], align 4 // CHECK5-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 0 // CHECK5-NEXT: store ptr [[G_ADDR]], ptr [[TMP11]], align 8 // CHECK5-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 1 -// CHECK5-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK5-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK5-NEXT: store ptr [[TMP13]], ptr [[TMP12]], align 8 // CHECK5-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 2 // CHECK5-NEXT: store ptr [[SIVAR_ADDR]], ptr [[TMP14]], align 8 @@ -2659,9 +2659,9 @@ int main() { // CHECK13-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK13-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 // CHECK13-NEXT: store i64 [[SIVAR]], ptr [[SIVAR_ADDR]], align 8 -// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK13-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK13-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META8:![0-9]+]], !align [[META9:![0-9]+]] +// CHECK13-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] +// CHECK13-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] // CHECK13-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK13-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK13-NEXT: [[TMP4:%.*]] = load i64, ptr [[T_VAR_CASTED]], align 8 @@ -2703,9 +2703,9 @@ int main() { // CHECK13-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK13-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 // CHECK13-NEXT: store i64 [[SIVAR]], ptr [[SIVAR_ADDR]], align 8 -// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK13-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK13-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] +// CHECK13-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] +// CHECK13-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] // CHECK13-NEXT: store i32 0, ptr [[DOTOMP_COMB_LB]], align 4 // CHECK13-NEXT: store i32 1, ptr [[DOTOMP_COMB_UB]], align 4 // CHECK13-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4 @@ -2860,9 +2860,9 @@ int main() { // CHECK13-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK13-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 // CHECK13-NEXT: store i64 [[SIVAR]], ptr [[SIVAR_ADDR]], align 8 -// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK13-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK13-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] +// CHECK13-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] +// CHECK13-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] // CHECK13-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK13-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 // CHECK13-NEXT: [[TMP3:%.*]] = load i64, ptr [[DOTPREVIOUS_LB__ADDR]], align 8 @@ -2987,14 +2987,14 @@ int main() { // CHECK13-NEXT: store i64 [[T_VAR]], ptr [[T_VAR_ADDR]], align 8 // CHECK13-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK13-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 -// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK13-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK13-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] +// CHECK13-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] +// CHECK13-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] // CHECK13-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 8 // CHECK13-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK13-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK13-NEXT: [[TMP4:%.*]] = load i64, ptr [[T_VAR_CASTED]], align 8 -// CHECK13-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK13-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META8]], !align [[META9]] // CHECK13-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB3]], i32 4, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l81.omp_outlined, ptr [[TMP0]], i64 [[TMP4]], ptr [[TMP1]], ptr [[TMP5]]) // CHECK13-NEXT: ret void // @@ -3029,9 +3029,9 @@ int main() { // CHECK13-NEXT: store i64 [[T_VAR]], ptr [[T_VAR_ADDR]], align 8 // CHECK13-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK13-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 -// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK13-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK13-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] +// CHECK13-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] +// CHECK13-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] // CHECK13-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 8 // CHECK13-NEXT: store i32 0, ptr [[DOTOMP_COMB_LB]], align 4 // CHECK13-NEXT: store i32 1, ptr [[DOTOMP_COMB_UB]], align 4 @@ -3053,7 +3053,7 @@ int main() { // CHECK13-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP3]] // CHECK13-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE4]], label [[OMP_ARRAYCPY_BODY]] // CHECK13: omp.arraycpy.done4: -// CHECK13-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK13-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META8]], !align [[META9]] // CHECK13-NEXT: call void @_ZN2StC1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) // CHECK13-NEXT: call void @_ZN1SIiEC1ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP4]], ptr noundef [[AGG_TMP6]]) // CHECK13-NEXT: call void @_ZN2StD1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) #[[ATTR3]] @@ -3090,7 +3090,7 @@ int main() { // CHECK13-NEXT: [[TMP16:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK13-NEXT: store i32 [[TMP16]], ptr [[T_VAR_CASTED]], align 4 // CHECK13-NEXT: [[TMP17:%.*]] = load i64, ptr [[T_VAR_CASTED]], align 8 -// CHECK13-NEXT: [[TMP18:%.*]] = load ptr, ptr [[_TMP7]], align 8 +// CHECK13-NEXT: [[TMP18:%.*]] = load ptr, ptr [[_TMP7]], align 8, !nonnull [[META8]], !align [[META9]] // CHECK13-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB3]], i32 6, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l81.omp_outlined.omp_outlined, i64 [[TMP13]], i64 [[TMP15]], ptr [[VEC2]], i64 [[TMP17]], ptr [[S_ARR3]], ptr [[TMP18]]) // CHECK13-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] // CHECK13: omp.inner.for.inc: @@ -3167,9 +3167,9 @@ int main() { // CHECK13-NEXT: store i64 [[T_VAR]], ptr [[T_VAR_ADDR]], align 8 // CHECK13-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK13-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 -// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK13-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK13-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] +// CHECK13-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] +// CHECK13-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] // CHECK13-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 8 // CHECK13-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK13-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 @@ -3197,7 +3197,7 @@ int main() { // CHECK13-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP5]] // CHECK13-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE5]], label [[OMP_ARRAYCPY_BODY]] // CHECK13: omp.arraycpy.done5: -// CHECK13-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK13-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META8]], !align [[META9]] // CHECK13-NEXT: call void @_ZN2StC1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP7]]) // CHECK13-NEXT: call void @_ZN1SIiEC1ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[VAR6]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP6]], ptr noundef [[AGG_TMP7]]) // CHECK13-NEXT: call void @_ZN2StD1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP7]]) #[[ATTR3]] @@ -3236,7 +3236,7 @@ int main() { // CHECK13-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP16]] to i64 // CHECK13-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i32], ptr [[VEC3]], i64 0, i64 [[IDXPROM]] // CHECK13-NEXT: store i32 [[TMP15]], ptr [[ARRAYIDX]], align 4 -// CHECK13-NEXT: [[TMP17:%.*]] = load ptr, ptr [[_TMP8]], align 8 +// CHECK13-NEXT: [[TMP17:%.*]] = load ptr, ptr [[_TMP8]], align 8, !nonnull [[META8]], !align [[META9]] // CHECK13-NEXT: [[TMP18:%.*]] = load i32, ptr [[I]], align 4 // CHECK13-NEXT: [[IDXPROM10:%.*]] = sext i32 [[TMP18]] to i64 // CHECK13-NEXT: [[ARRAYIDX11:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR4]], i64 0, i64 [[IDXPROM10]] @@ -3321,7 +3321,7 @@ int main() { // CHECK13-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8 // CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK13-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] // CHECK13-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP0]], i32 0, i32 0 // CHECK13-NEXT: [[TMP1:%.*]] = load float, ptr [[F2]], align 4 // CHECK13-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -3352,7 +3352,7 @@ int main() { // CHECK13-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8 // CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK13-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] // CHECK13-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0]], ptr [[TMP0]], i32 0, i32 0 // CHECK13-NEXT: [[TMP1:%.*]] = load i32, ptr [[F2]], align 4 // CHECK13-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -3379,9 +3379,9 @@ int main() { // CHECK15-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK15-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 // CHECK15-NEXT: store i32 [[SIVAR]], ptr [[SIVAR_ADDR]], align 4 -// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK15-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK15-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META9:![0-9]+]], !align [[META10:![0-9]+]] +// CHECK15-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META9]], !align [[META10]] +// CHECK15-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META9]], !align [[META10]] // CHECK15-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK15-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK15-NEXT: [[TMP4:%.*]] = load i32, ptr [[T_VAR_CASTED]], align 4 @@ -3423,9 +3423,9 @@ int main() { // CHECK15-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK15-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 // CHECK15-NEXT: store i32 [[SIVAR]], ptr [[SIVAR_ADDR]], align 4 -// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK15-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK15-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META9]], !align [[META10]] +// CHECK15-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META9]], !align [[META10]] +// CHECK15-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META9]], !align [[META10]] // CHECK15-NEXT: store i32 0, ptr [[DOTOMP_COMB_LB]], align 4 // CHECK15-NEXT: store i32 1, ptr [[DOTOMP_COMB_UB]], align 4 // CHECK15-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4 @@ -3578,9 +3578,9 @@ int main() { // CHECK15-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK15-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 // CHECK15-NEXT: store i32 [[SIVAR]], ptr [[SIVAR_ADDR]], align 4 -// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK15-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK15-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META9]], !align [[META10]] +// CHECK15-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META9]], !align [[META10]] +// CHECK15-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META9]], !align [[META10]] // CHECK15-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK15-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 // CHECK15-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTPREVIOUS_LB__ADDR]], align 4 @@ -3701,14 +3701,14 @@ int main() { // CHECK15-NEXT: store i32 [[T_VAR]], ptr [[T_VAR_ADDR]], align 4 // CHECK15-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK15-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 -// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK15-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK15-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META9]], !align [[META10]] +// CHECK15-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META9]], !align [[META10]] +// CHECK15-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META9]], !align [[META10]] // CHECK15-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 4 // CHECK15-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK15-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK15-NEXT: [[TMP4:%.*]] = load i32, ptr [[T_VAR_CASTED]], align 4 -// CHECK15-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK15-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META9]], !align [[META10]] // CHECK15-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB3]], i32 4, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l81.omp_outlined, ptr [[TMP0]], i32 [[TMP4]], ptr [[TMP1]], ptr [[TMP5]]) // CHECK15-NEXT: ret void // @@ -3743,9 +3743,9 @@ int main() { // CHECK15-NEXT: store i32 [[T_VAR]], ptr [[T_VAR_ADDR]], align 4 // CHECK15-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK15-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 -// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK15-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK15-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META9]], !align [[META10]] +// CHECK15-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META9]], !align [[META10]] +// CHECK15-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META9]], !align [[META10]] // CHECK15-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 4 // CHECK15-NEXT: store i32 0, ptr [[DOTOMP_COMB_LB]], align 4 // CHECK15-NEXT: store i32 1, ptr [[DOTOMP_COMB_UB]], align 4 @@ -3767,7 +3767,7 @@ int main() { // CHECK15-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP3]] // CHECK15-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE4]], label [[OMP_ARRAYCPY_BODY]] // CHECK15: omp.arraycpy.done4: -// CHECK15-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK15-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META9]], !align [[META10]] // CHECK15-NEXT: call void @_ZN2StC1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) // CHECK15-NEXT: call void @_ZN1SIiEC1ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP4]], ptr noundef [[AGG_TMP6]]) // CHECK15-NEXT: call void @_ZN2StD1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) #[[ATTR3]] @@ -3802,7 +3802,7 @@ int main() { // CHECK15-NEXT: [[TMP14:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK15-NEXT: store i32 [[TMP14]], ptr [[T_VAR_CASTED]], align 4 // CHECK15-NEXT: [[TMP15:%.*]] = load i32, ptr [[T_VAR_CASTED]], align 4 -// CHECK15-NEXT: [[TMP16:%.*]] = load ptr, ptr [[_TMP7]], align 4 +// CHECK15-NEXT: [[TMP16:%.*]] = load ptr, ptr [[_TMP7]], align 4, !nonnull [[META9]], !align [[META10]] // CHECK15-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB3]], i32 6, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l81.omp_outlined.omp_outlined, i32 [[TMP12]], i32 [[TMP13]], ptr [[VEC2]], i32 [[TMP15]], ptr [[S_ARR3]], ptr [[TMP16]]) // CHECK15-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] // CHECK15: omp.inner.for.inc: @@ -3879,9 +3879,9 @@ int main() { // CHECK15-NEXT: store i32 [[T_VAR]], ptr [[T_VAR_ADDR]], align 4 // CHECK15-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK15-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 -// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK15-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK15-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META9]], !align [[META10]] +// CHECK15-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META9]], !align [[META10]] +// CHECK15-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META9]], !align [[META10]] // CHECK15-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 4 // CHECK15-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK15-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 @@ -3907,7 +3907,7 @@ int main() { // CHECK15-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP5]] // CHECK15-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE4]], label [[OMP_ARRAYCPY_BODY]] // CHECK15: omp.arraycpy.done4: -// CHECK15-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK15-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META9]], !align [[META10]] // CHECK15-NEXT: call void @_ZN2StC1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) // CHECK15-NEXT: call void @_ZN1SIiEC1ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP6]], ptr noundef [[AGG_TMP6]]) // CHECK15-NEXT: call void @_ZN2StD1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) #[[ATTR3]] @@ -3945,7 +3945,7 @@ int main() { // CHECK15-NEXT: [[TMP16:%.*]] = load i32, ptr [[I]], align 4 // CHECK15-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i32], ptr [[VEC2]], i32 0, i32 [[TMP16]] // CHECK15-NEXT: store i32 [[TMP15]], ptr [[ARRAYIDX]], align 4 -// CHECK15-NEXT: [[TMP17:%.*]] = load ptr, ptr [[_TMP7]], align 4 +// CHECK15-NEXT: [[TMP17:%.*]] = load ptr, ptr [[_TMP7]], align 4, !nonnull [[META9]], !align [[META10]] // CHECK15-NEXT: [[TMP18:%.*]] = load i32, ptr [[I]], align 4 // CHECK15-NEXT: [[ARRAYIDX9:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR3]], i32 0, i32 [[TMP18]] // CHECK15-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[ARRAYIDX9]], ptr align 4 [[TMP17]], i32 4, i1 false) @@ -4029,7 +4029,7 @@ int main() { // CHECK15-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4 // CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 // CHECK15-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4 +// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4, !nonnull [[META9]], !align [[META10]] // CHECK15-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP0]], i32 0, i32 0 // CHECK15-NEXT: [[TMP1:%.*]] = load float, ptr [[F2]], align 4 // CHECK15-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -4060,7 +4060,7 @@ int main() { // CHECK15-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4 // CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 // CHECK15-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4 +// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4, !nonnull [[META9]], !align [[META10]] // CHECK15-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0]], ptr [[TMP0]], i32 0, i32 0 // CHECK15-NEXT: [[TMP1:%.*]] = load i32, ptr [[F2]], align 4 // CHECK15-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -4089,7 +4089,7 @@ int main() { // CHECK17-NEXT: [[TMP0:%.*]] = load i32, ptr [[G_ADDR]], align 4 // CHECK17-NEXT: store i32 [[TMP0]], ptr [[G_CASTED]], align 4 // CHECK17-NEXT: [[TMP1:%.*]] = load i64, ptr [[G_CASTED]], align 8 -// CHECK17-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK17-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META6:![0-9]+]], !align [[META7:![0-9]+]] // CHECK17-NEXT: [[TMP3:%.*]] = load volatile i32, ptr [[TMP2]], align 4 // CHECK17-NEXT: store i32 [[TMP3]], ptr [[G1_CASTED]], align 4 // CHECK17-NEXT: [[TMP4:%.*]] = load i64, ptr [[G1_CASTED]], align 8 @@ -4159,7 +4159,7 @@ int main() { // CHECK17-NEXT: [[TMP11:%.*]] = load i32, ptr [[G_ADDR]], align 4 // CHECK17-NEXT: store i32 [[TMP11]], ptr [[G_CASTED]], align 4 // CHECK17-NEXT: [[TMP12:%.*]] = load i64, ptr [[G_CASTED]], align 8 -// CHECK17-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK17-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META6]], !align [[META7]] // CHECK17-NEXT: [[TMP14:%.*]] = load volatile i32, ptr [[TMP13]], align 4 // CHECK17-NEXT: store i32 [[TMP14]], ptr [[G1_CASTED]], align 4 // CHECK17-NEXT: [[TMP15:%.*]] = load i64, ptr [[G1_CASTED]], align 8 @@ -4246,13 +4246,13 @@ int main() { // CHECK17-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]] // CHECK17-NEXT: store i32 [[ADD]], ptr [[I]], align 4 // CHECK17-NEXT: store i32 1, ptr [[G_ADDR]], align 4 -// CHECK17-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK17-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META6]], !align [[META7]] // CHECK17-NEXT: store volatile i32 1, ptr [[TMP10]], align 4 // CHECK17-NEXT: store i32 2, ptr [[SIVAR_ADDR]], align 4 // CHECK17-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 0 // CHECK17-NEXT: store ptr [[G_ADDR]], ptr [[TMP11]], align 8 // CHECK17-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 1 -// CHECK17-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK17-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META6]], !align [[META7]] // CHECK17-NEXT: store ptr [[TMP13]], ptr [[TMP12]], align 8 // CHECK17-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 2 // CHECK17-NEXT: store ptr [[SIVAR_ADDR]], ptr [[TMP14]], align 8 diff --git a/clang/test/OpenMP/teams_distribute_firstprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_firstprivate_codegen.cpp index 294fcba7872b3..f3c9565a17656 100644 --- a/clang/test/OpenMP/teams_distribute_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_firstprivate_codegen.cpp @@ -357,9 +357,9 @@ int main() { // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 // CHECK1-NEXT: store i64 [[SIVAR]], ptr [[SIVAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META7:![0-9]+]], !align [[META8:![0-9]+]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK1-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK1-NEXT: [[TMP4:%.*]] = load i64, ptr [[T_VAR_CASTED]], align 8 @@ -399,9 +399,9 @@ int main() { // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 // CHECK1-NEXT: store i64 [[SIVAR]], ptr [[SIVAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK1-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 // CHECK1-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4 @@ -553,14 +553,14 @@ int main() { // CHECK1-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[S_ARR]], i64 1 // CHECK1-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], i32 noundef signext 2) // CHECK1-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: store ptr [[TMP0]], ptr [[TMP]], align 8 // CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[T_VAR]], align 4 // CHECK1-NEXT: store i32 [[TMP1]], ptr [[T_VAR_CASTED]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = load i64, ptr [[T_VAR_CASTED]], align 8 -// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 8 -// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8 -// CHECK1-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: store i64 [[TMP2]], ptr [[TMP6]], align 8 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 @@ -660,7 +660,7 @@ int main() { // CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8 // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP0]], i32 0, i32 0 // CHECK1-NEXT: [[TMP1:%.*]] = load float, ptr [[F2]], align 4 // CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -716,14 +716,14 @@ int main() { // CHECK1-NEXT: store ptr [[VEC]], ptr [[VEC_ADDR]], align 8 // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 8 // CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK1-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK1-NEXT: [[TMP4:%.*]] = load i64, ptr [[T_VAR_CASTED]], align 8 -// CHECK1-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK1-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB2]], i32 4, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l56.omp_outlined, ptr [[TMP0]], i64 [[TMP4]], ptr [[TMP1]], ptr [[TMP5]]) // CHECK1-NEXT: ret void // @@ -757,9 +757,9 @@ int main() { // CHECK1-NEXT: store i64 [[T_VAR]], ptr [[T_VAR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 8 // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK1-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 @@ -781,7 +781,7 @@ int main() { // CHECK1-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP3]] // CHECK1-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE4]], label [[OMP_ARRAYCPY_BODY]] // CHECK1: omp.arraycpy.done4: -// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: call void @_ZN2StC1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) // CHECK1-NEXT: call void @_ZN1SIiEC1ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP4]], ptr noundef [[AGG_TMP6]]) // CHECK1-NEXT: call void @_ZN2StD1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) #[[ATTR2]] @@ -820,7 +820,7 @@ int main() { // CHECK1-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP14]] to i64 // CHECK1-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i32], ptr [[VEC2]], i64 0, i64 [[IDXPROM]] // CHECK1-NEXT: store i32 [[TMP13]], ptr [[ARRAYIDX]], align 4 -// CHECK1-NEXT: [[TMP15:%.*]] = load ptr, ptr [[_TMP7]], align 8 +// CHECK1-NEXT: [[TMP15:%.*]] = load ptr, ptr [[_TMP7]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[I]], align 4 // CHECK1-NEXT: [[IDXPROM9:%.*]] = sext i32 [[TMP16]] to i64 // CHECK1-NEXT: [[ARRAYIDX10:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR3]], i64 0, i64 [[IDXPROM9]] @@ -917,7 +917,7 @@ int main() { // CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8 // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0]], ptr [[TMP0]], i32 0, i32 0 // CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[F2]], align 4 // CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -1160,9 +1160,9 @@ int main() { // CHECK3-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 // CHECK3-NEXT: store i32 [[SIVAR]], ptr [[SIVAR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META8:![0-9]+]], !align [[META9:![0-9]+]] +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK3-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK3-NEXT: [[TMP4:%.*]] = load i32, ptr [[T_VAR_CASTED]], align 4 @@ -1202,9 +1202,9 @@ int main() { // CHECK3-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 // CHECK3-NEXT: store i32 [[SIVAR]], ptr [[SIVAR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK3-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 // CHECK3-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4 @@ -1354,14 +1354,14 @@ int main() { // CHECK3-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[S_ARR]], i32 1 // CHECK3-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], i32 noundef 2) // CHECK3-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: store ptr [[TMP0]], ptr [[TMP]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = load i32, ptr [[T_VAR]], align 4 // CHECK3-NEXT: store i32 [[TMP1]], ptr [[T_VAR_CASTED]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = load i32, ptr [[T_VAR_CASTED]], align 4 -// CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 4 -// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 4 -// CHECK3-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: store i32 [[TMP2]], ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 @@ -1461,7 +1461,7 @@ int main() { // CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4 // CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 // CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP0]], i32 0, i32 0 // CHECK3-NEXT: [[TMP1:%.*]] = load float, ptr [[F2]], align 4 // CHECK3-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -1517,14 +1517,14 @@ int main() { // CHECK3-NEXT: store ptr [[VEC]], ptr [[VEC_ADDR]], align 4 // CHECK3-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 4 // CHECK3-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK3-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK3-NEXT: [[TMP4:%.*]] = load i32, ptr [[T_VAR_CASTED]], align 4 -// CHECK3-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK3-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB2]], i32 4, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l56.omp_outlined, ptr [[TMP0]], i32 [[TMP4]], ptr [[TMP1]], ptr [[TMP5]]) // CHECK3-NEXT: ret void // @@ -1558,9 +1558,9 @@ int main() { // CHECK3-NEXT: store i32 [[T_VAR]], ptr [[T_VAR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 4 // CHECK3-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK3-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 @@ -1582,7 +1582,7 @@ int main() { // CHECK3-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP3]] // CHECK3-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE4]], label [[OMP_ARRAYCPY_BODY]] // CHECK3: omp.arraycpy.done4: -// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: call void @_ZN2StC1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) // CHECK3-NEXT: call void @_ZN1SIiEC1ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP4]], ptr noundef [[AGG_TMP6]]) // CHECK3-NEXT: call void @_ZN2StD1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) #[[ATTR2]] @@ -1620,7 +1620,7 @@ int main() { // CHECK3-NEXT: [[TMP14:%.*]] = load i32, ptr [[I]], align 4 // CHECK3-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i32], ptr [[VEC2]], i32 0, i32 [[TMP14]] // CHECK3-NEXT: store i32 [[TMP13]], ptr [[ARRAYIDX]], align 4 -// CHECK3-NEXT: [[TMP15:%.*]] = load ptr, ptr [[_TMP7]], align 4 +// CHECK3-NEXT: [[TMP15:%.*]] = load ptr, ptr [[_TMP7]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: [[TMP16:%.*]] = load i32, ptr [[I]], align 4 // CHECK3-NEXT: [[ARRAYIDX9:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR3]], i32 0, i32 [[TMP16]] // CHECK3-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[ARRAYIDX9]], ptr align 4 [[TMP15]], i32 4, i1 false) @@ -1716,7 +1716,7 @@ int main() { // CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4 // CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 // CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0]], ptr [[TMP0]], i32 0, i32 0 // CHECK3-NEXT: [[TMP1:%.*]] = load i32, ptr [[F2]], align 4 // CHECK3-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -1884,7 +1884,7 @@ int main() { // CHECK9-NEXT: [[TMP0:%.*]] = load i32, ptr [[G_ADDR]], align 4 // CHECK9-NEXT: store i32 [[TMP0]], ptr [[G_CASTED]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = load i64, ptr [[G_CASTED]], align 8 -// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META5:![0-9]+]], !align [[META6:![0-9]+]] // CHECK9-NEXT: [[TMP3:%.*]] = load volatile i32, ptr [[TMP2]], align 4 // CHECK9-NEXT: store i32 [[TMP3]], ptr [[G1_CASTED]], align 4 // CHECK9-NEXT: [[TMP4:%.*]] = load i64, ptr [[G1_CASTED]], align 8 @@ -1950,13 +1950,13 @@ int main() { // CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]] // CHECK9-NEXT: store i32 [[ADD]], ptr [[I]], align 4 // CHECK9-NEXT: store i32 1, ptr [[G_ADDR]], align 4 -// CHECK9-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK9-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK9-NEXT: store volatile i32 1, ptr [[TMP8]], align 4 // CHECK9-NEXT: store i32 2, ptr [[SIVAR_ADDR]], align 4 // CHECK9-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 0 // CHECK9-NEXT: store ptr [[G_ADDR]], ptr [[TMP9]], align 8 // CHECK9-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 1 -// CHECK9-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK9-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK9-NEXT: store ptr [[TMP11]], ptr [[TMP10]], align 8 // CHECK9-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 2 // CHECK9-NEXT: store ptr [[SIVAR_ADDR]], ptr [[TMP12]], align 8 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp index d742b0a85af42..037aa12d57226 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp @@ -391,9 +391,9 @@ int main() { // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 // CHECK1-NEXT: store i64 [[SIVAR]], ptr [[SIVAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META7:![0-9]+]], !align [[META8:![0-9]+]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK1-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK1-NEXT: [[TMP4:%.*]] = load i64, ptr [[T_VAR_CASTED]], align 8 @@ -435,9 +435,9 @@ int main() { // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 // CHECK1-NEXT: store i64 [[SIVAR]], ptr [[SIVAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_COMB_LB]], align 4 // CHECK1-NEXT: store i32 1, ptr [[DOTOMP_COMB_UB]], align 4 // CHECK1-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4 @@ -592,9 +592,9 @@ int main() { // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 // CHECK1-NEXT: store i64 [[SIVAR]], ptr [[SIVAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK1-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 // CHECK1-NEXT: [[TMP3:%.*]] = load i64, ptr [[DOTPREVIOUS_LB__ADDR]], align 8 @@ -717,14 +717,14 @@ int main() { // CHECK1-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[S_ARR]], i64 1 // CHECK1-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], i32 noundef signext 2) // CHECK1-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: store ptr [[TMP0]], ptr [[TMP]], align 8 // CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[T_VAR]], align 4 // CHECK1-NEXT: store i32 [[TMP1]], ptr [[T_VAR_CASTED]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = load i64, ptr [[T_VAR_CASTED]], align 8 -// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 8 -// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8 -// CHECK1-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: store i64 [[TMP2]], ptr [[TMP6]], align 8 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 @@ -824,7 +824,7 @@ int main() { // CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8 // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP0]], i32 0, i32 0 // CHECK1-NEXT: [[TMP1:%.*]] = load float, ptr [[F2]], align 4 // CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -880,14 +880,14 @@ int main() { // CHECK1-NEXT: store ptr [[VEC]], ptr [[VEC_ADDR]], align 8 // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 8 // CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK1-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK1-NEXT: [[TMP4:%.*]] = load i64, ptr [[T_VAR_CASTED]], align 8 -// CHECK1-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK1-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB3]], i32 4, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l56.omp_outlined, ptr [[TMP0]], i64 [[TMP4]], ptr [[TMP1]], ptr [[TMP5]]) // CHECK1-NEXT: ret void // @@ -922,9 +922,9 @@ int main() { // CHECK1-NEXT: store i64 [[T_VAR]], ptr [[T_VAR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 8 // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_COMB_LB]], align 4 // CHECK1-NEXT: store i32 1, ptr [[DOTOMP_COMB_UB]], align 4 @@ -946,7 +946,7 @@ int main() { // CHECK1-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP3]] // CHECK1-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE4]], label [[OMP_ARRAYCPY_BODY]] // CHECK1: omp.arraycpy.done4: -// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: call void @_ZN2StC1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) // CHECK1-NEXT: call void @_ZN1SIiEC1ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP4]], ptr noundef [[AGG_TMP6]]) // CHECK1-NEXT: call void @_ZN2StD1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) #[[ATTR2]] @@ -983,7 +983,7 @@ int main() { // CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK1-NEXT: store i32 [[TMP16]], ptr [[T_VAR_CASTED]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = load i64, ptr [[T_VAR_CASTED]], align 8 -// CHECK1-NEXT: [[TMP18:%.*]] = load ptr, ptr [[_TMP7]], align 8 +// CHECK1-NEXT: [[TMP18:%.*]] = load ptr, ptr [[_TMP7]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB3]], i32 6, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l56.omp_outlined.omp_outlined, i64 [[TMP13]], i64 [[TMP15]], ptr [[VEC2]], i64 [[TMP17]], ptr [[S_ARR3]], ptr [[TMP18]]) // CHECK1-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] // CHECK1: omp.inner.for.inc: @@ -1060,9 +1060,9 @@ int main() { // CHECK1-NEXT: store i64 [[T_VAR]], ptr [[T_VAR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK1-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 8 // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK1-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 @@ -1090,7 +1090,7 @@ int main() { // CHECK1-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP5]] // CHECK1-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE5]], label [[OMP_ARRAYCPY_BODY]] // CHECK1: omp.arraycpy.done5: -// CHECK1-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK1-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: call void @_ZN2StC1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP7]]) // CHECK1-NEXT: call void @_ZN1SIiEC1ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[VAR6]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP6]], ptr noundef [[AGG_TMP7]]) // CHECK1-NEXT: call void @_ZN2StD1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP7]]) #[[ATTR2]] @@ -1129,7 +1129,7 @@ int main() { // CHECK1-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP16]] to i64 // CHECK1-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i32], ptr [[VEC3]], i64 0, i64 [[IDXPROM]] // CHECK1-NEXT: store i32 [[TMP15]], ptr [[ARRAYIDX]], align 4 -// CHECK1-NEXT: [[TMP17:%.*]] = load ptr, ptr [[_TMP8]], align 8 +// CHECK1-NEXT: [[TMP17:%.*]] = load ptr, ptr [[_TMP8]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: [[TMP18:%.*]] = load i32, ptr [[I]], align 4 // CHECK1-NEXT: [[IDXPROM10:%.*]] = sext i32 [[TMP18]] to i64 // CHECK1-NEXT: [[ARRAYIDX11:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR4]], i64 0, i64 [[IDXPROM10]] @@ -1211,7 +1211,7 @@ int main() { // CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8 // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !nonnull [[META7]], !align [[META8]] // CHECK1-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0]], ptr [[TMP0]], i32 0, i32 0 // CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[F2]], align 4 // CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -1454,9 +1454,9 @@ int main() { // CHECK3-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 // CHECK3-NEXT: store i32 [[SIVAR]], ptr [[SIVAR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META8:![0-9]+]], !align [[META9:![0-9]+]] +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK3-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK3-NEXT: [[TMP4:%.*]] = load i32, ptr [[T_VAR_CASTED]], align 4 @@ -1498,9 +1498,9 @@ int main() { // CHECK3-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 // CHECK3-NEXT: store i32 [[SIVAR]], ptr [[SIVAR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: store i32 0, ptr [[DOTOMP_COMB_LB]], align 4 // CHECK3-NEXT: store i32 1, ptr [[DOTOMP_COMB_UB]], align 4 // CHECK3-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4 @@ -1653,9 +1653,9 @@ int main() { // CHECK3-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 // CHECK3-NEXT: store i32 [[SIVAR]], ptr [[SIVAR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK3-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 // CHECK3-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTPREVIOUS_LB__ADDR]], align 4 @@ -1774,14 +1774,14 @@ int main() { // CHECK3-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[S_ARR]], i32 1 // CHECK3-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], i32 noundef 2) // CHECK3-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: store ptr [[TMP0]], ptr [[TMP]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = load i32, ptr [[T_VAR]], align 4 // CHECK3-NEXT: store i32 [[TMP1]], ptr [[T_VAR_CASTED]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = load i32, ptr [[T_VAR_CASTED]], align 4 -// CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 4 -// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 4 -// CHECK3-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: store i32 [[TMP2]], ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 @@ -1881,7 +1881,7 @@ int main() { // CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4 // CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 // CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP0]], i32 0, i32 0 // CHECK3-NEXT: [[TMP1:%.*]] = load float, ptr [[F2]], align 4 // CHECK3-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -1937,14 +1937,14 @@ int main() { // CHECK3-NEXT: store ptr [[VEC]], ptr [[VEC_ADDR]], align 4 // CHECK3-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 4 // CHECK3-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK3-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK3-NEXT: [[TMP4:%.*]] = load i32, ptr [[T_VAR_CASTED]], align 4 -// CHECK3-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK3-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB3]], i32 4, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l56.omp_outlined, ptr [[TMP0]], i32 [[TMP4]], ptr [[TMP1]], ptr [[TMP5]]) // CHECK3-NEXT: ret void // @@ -1979,9 +1979,9 @@ int main() { // CHECK3-NEXT: store i32 [[T_VAR]], ptr [[T_VAR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 4 // CHECK3-NEXT: store i32 0, ptr [[DOTOMP_COMB_LB]], align 4 // CHECK3-NEXT: store i32 1, ptr [[DOTOMP_COMB_UB]], align 4 @@ -2003,7 +2003,7 @@ int main() { // CHECK3-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP3]] // CHECK3-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE4]], label [[OMP_ARRAYCPY_BODY]] // CHECK3: omp.arraycpy.done4: -// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: call void @_ZN2StC1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) // CHECK3-NEXT: call void @_ZN1SIiEC1ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP4]], ptr noundef [[AGG_TMP6]]) // CHECK3-NEXT: call void @_ZN2StD1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) #[[ATTR2]] @@ -2038,7 +2038,7 @@ int main() { // CHECK3-NEXT: [[TMP14:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK3-NEXT: store i32 [[TMP14]], ptr [[T_VAR_CASTED]], align 4 // CHECK3-NEXT: [[TMP15:%.*]] = load i32, ptr [[T_VAR_CASTED]], align 4 -// CHECK3-NEXT: [[TMP16:%.*]] = load ptr, ptr [[_TMP7]], align 4 +// CHECK3-NEXT: [[TMP16:%.*]] = load ptr, ptr [[_TMP7]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB3]], i32 6, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l56.omp_outlined.omp_outlined, i32 [[TMP12]], i32 [[TMP13]], ptr [[VEC2]], i32 [[TMP15]], ptr [[S_ARR3]], ptr [[TMP16]]) // CHECK3-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] // CHECK3: omp.inner.for.inc: @@ -2115,9 +2115,9 @@ int main() { // CHECK3-NEXT: store i32 [[T_VAR]], ptr [[T_VAR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK3-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: store ptr [[TMP2]], ptr [[TMP]], align 4 // CHECK3-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK3-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 @@ -2143,7 +2143,7 @@ int main() { // CHECK3-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP5]] // CHECK3-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE4]], label [[OMP_ARRAYCPY_BODY]] // CHECK3: omp.arraycpy.done4: -// CHECK3-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP]], align 4 +// CHECK3-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: call void @_ZN2StC1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) // CHECK3-NEXT: call void @_ZN1SIiEC1ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP6]], ptr noundef [[AGG_TMP6]]) // CHECK3-NEXT: call void @_ZN2StD1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[AGG_TMP6]]) #[[ATTR2]] @@ -2181,7 +2181,7 @@ int main() { // CHECK3-NEXT: [[TMP16:%.*]] = load i32, ptr [[I]], align 4 // CHECK3-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i32], ptr [[VEC2]], i32 0, i32 [[TMP16]] // CHECK3-NEXT: store i32 [[TMP15]], ptr [[ARRAYIDX]], align 4 -// CHECK3-NEXT: [[TMP17:%.*]] = load ptr, ptr [[_TMP7]], align 4 +// CHECK3-NEXT: [[TMP17:%.*]] = load ptr, ptr [[_TMP7]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: [[TMP18:%.*]] = load i32, ptr [[I]], align 4 // CHECK3-NEXT: [[ARRAYIDX9:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR3]], i32 0, i32 [[TMP18]] // CHECK3-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[ARRAYIDX9]], ptr align 4 [[TMP17]], i32 4, i1 false) @@ -2262,7 +2262,7 @@ int main() { // CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4 // CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 // CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK3-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0]], ptr [[TMP0]], i32 0, i32 0 // CHECK3-NEXT: [[TMP1:%.*]] = load i32, ptr [[F2]], align 4 // CHECK3-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -2430,7 +2430,7 @@ int main() { // CHECK9-NEXT: [[TMP0:%.*]] = load i32, ptr [[G_ADDR]], align 4 // CHECK9-NEXT: store i32 [[TMP0]], ptr [[G_CASTED]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = load i64, ptr [[G_CASTED]], align 8 -// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META5:![0-9]+]], !align [[META6:![0-9]+]] // CHECK9-NEXT: [[TMP3:%.*]] = load volatile i32, ptr [[TMP2]], align 4 // CHECK9-NEXT: store i32 [[TMP3]], ptr [[G1_CASTED]], align 4 // CHECK9-NEXT: [[TMP4:%.*]] = load i64, ptr [[G1_CASTED]], align 8 @@ -2500,7 +2500,7 @@ int main() { // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[G_ADDR]], align 4 // CHECK9-NEXT: store i32 [[TMP11]], ptr [[G_CASTED]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = load i64, ptr [[G_CASTED]], align 8 -// CHECK9-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK9-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK9-NEXT: [[TMP14:%.*]] = load volatile i32, ptr [[TMP13]], align 4 // CHECK9-NEXT: store i32 [[TMP14]], ptr [[G1_CASTED]], align 4 // CHECK9-NEXT: [[TMP15:%.*]] = load i64, ptr [[G1_CASTED]], align 8 @@ -2587,13 +2587,13 @@ int main() { // CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]] // CHECK9-NEXT: store i32 [[ADD]], ptr [[I]], align 4 // CHECK9-NEXT: store i32 1, ptr [[G_ADDR]], align 4 -// CHECK9-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK9-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK9-NEXT: store volatile i32 1, ptr [[TMP10]], align 4 // CHECK9-NEXT: store i32 2, ptr [[SIVAR_ADDR]], align 4 // CHECK9-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 0 // CHECK9-NEXT: store ptr [[G_ADDR]], ptr [[TMP11]], align 8 // CHECK9-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 1 -// CHECK9-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK9-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP]], align 8, !nonnull [[META5]], !align [[META6]] // CHECK9-NEXT: store ptr [[TMP13]], ptr [[TMP12]], align 8 // CHECK9-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 2 // CHECK9-NEXT: store ptr [[SIVAR_ADDR]], ptr [[TMP14]], align 8 diff --git a/clang/test/OpenMP/teams_firstprivate_codegen.cpp b/clang/test/OpenMP/teams_firstprivate_codegen.cpp index 6f21c9e31bd8d..fec8fcb78f91e 100644 --- a/clang/test/OpenMP/teams_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_firstprivate_codegen.cpp @@ -458,9 +458,9 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK9-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK9-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 // CHECK9-NEXT: store i64 [[SIVAR]], ptr [[SIVAR_ADDR]], align 8 -// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK9-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META11:![0-9]+]], !align [[META12:![0-9]+]] +// CHECK9-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META11]], !align [[META12]] +// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META11]], !align [[META12]] // CHECK9-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK9-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK9-NEXT: [[TMP4:%.*]] = load i64, ptr [[T_VAR_CASTED]], align 8 @@ -493,9 +493,9 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK9-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK9-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 // CHECK9-NEXT: store i64 [[SIVAR]], ptr [[SIVAR_ADDR]], align 8 -// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK9-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META11]], !align [[META12]] +// CHECK9-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META11]], !align [[META12]] +// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META11]], !align [[META12]] // CHECK9-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VEC1]], ptr align 4 [[TMP0]], i64 8, i1 false) // CHECK9-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR2]], i32 0, i32 0 // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN]], i64 2 @@ -808,7 +808,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK9-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8 // CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK9-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !nonnull [[META11]], !align [[META12]] // CHECK9-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP0]], i32 0, i32 0 // CHECK9-NEXT: [[TMP1:%.*]] = load float, ptr [[F2]], align 4 // CHECK9-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -872,9 +872,9 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK9-NEXT: store ptr [[VEC]], ptr [[VEC_ADDR]], align 8 // CHECK9-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK9-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 -// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK9-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META11]], !align [[META12]] +// CHECK9-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META11]], !align [[META12]] +// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META11]], !align [[META12]] // CHECK9-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK9-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK9-NEXT: [[TMP4:%.*]] = load i64, ptr [[T_VAR_CASTED]], align 8 @@ -902,9 +902,9 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK9-NEXT: store i64 [[T_VAR]], ptr [[T_VAR_ADDR]], align 8 // CHECK9-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 8 // CHECK9-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 8 -// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8 -// CHECK9-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8 -// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8 +// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 8, !nonnull [[META11]], !align [[META12]] +// CHECK9-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 8, !nonnull [[META11]], !align [[META12]] +// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 8, !nonnull [[META11]], !align [[META12]] // CHECK9-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 128 [[VEC1]], ptr align 128 [[TMP0]], i64 8, i1 false) // CHECK9-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR2]], i32 0, i32 0 // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN]], i64 2 @@ -1032,7 +1032,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK9-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8 // CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK9-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8 +// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !nonnull [[META11]], !align [[META12]] // CHECK9-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0]], ptr [[TMP0]], i32 0, i32 0 // CHECK9-NEXT: [[TMP1:%.*]] = load i32, ptr [[F2]], align 4 // CHECK9-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -1250,9 +1250,9 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK11-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK11-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 // CHECK11-NEXT: store i32 [[SIVAR]], ptr [[SIVAR_ADDR]], align 4 -// CHECK11-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK11-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK11-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK11-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META12:![0-9]+]], !align [[META13:![0-9]+]] +// CHECK11-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META12]], !align [[META13]] +// CHECK11-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META12]], !align [[META13]] // CHECK11-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK11-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK11-NEXT: [[TMP4:%.*]] = load i32, ptr [[T_VAR_CASTED]], align 4 @@ -1285,9 +1285,9 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK11-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK11-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 // CHECK11-NEXT: store i32 [[SIVAR]], ptr [[SIVAR_ADDR]], align 4 -// CHECK11-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK11-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK11-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK11-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META12]], !align [[META13]] +// CHECK11-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META12]], !align [[META13]] +// CHECK11-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META12]], !align [[META13]] // CHECK11-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[VEC1]], ptr align 4 [[TMP0]], i32 8, i1 false) // CHECK11-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR2]], i32 0, i32 0 // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN]], i32 2 @@ -1600,7 +1600,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK11-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4 // CHECK11-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 // CHECK11-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK11-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4 +// CHECK11-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4, !nonnull [[META12]], !align [[META13]] // CHECK11-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP0]], i32 0, i32 0 // CHECK11-NEXT: [[TMP1:%.*]] = load float, ptr [[F2]], align 4 // CHECK11-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -1664,9 +1664,9 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK11-NEXT: store ptr [[VEC]], ptr [[VEC_ADDR]], align 4 // CHECK11-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK11-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 -// CHECK11-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK11-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK11-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK11-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META12]], !align [[META13]] +// CHECK11-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META12]], !align [[META13]] +// CHECK11-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META12]], !align [[META13]] // CHECK11-NEXT: [[TMP3:%.*]] = load i32, ptr [[T_VAR_ADDR]], align 4 // CHECK11-NEXT: store i32 [[TMP3]], ptr [[T_VAR_CASTED]], align 4 // CHECK11-NEXT: [[TMP4:%.*]] = load i32, ptr [[T_VAR_CASTED]], align 4 @@ -1694,9 +1694,9 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK11-NEXT: store i32 [[T_VAR]], ptr [[T_VAR_ADDR]], align 4 // CHECK11-NEXT: store ptr [[S_ARR]], ptr [[S_ARR_ADDR]], align 4 // CHECK11-NEXT: store ptr [[VAR]], ptr [[VAR_ADDR]], align 4 -// CHECK11-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4 -// CHECK11-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4 -// CHECK11-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4 +// CHECK11-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VEC_ADDR]], align 4, !nonnull [[META12]], !align [[META13]] +// CHECK11-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ARR_ADDR]], align 4, !nonnull [[META12]], !align [[META13]] +// CHECK11-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VAR_ADDR]], align 4, !nonnull [[META12]], !align [[META13]] // CHECK11-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 128 [[VEC1]], ptr align 128 [[TMP0]], i32 8, i1 false) // CHECK11-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR2]], i32 0, i32 0 // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN]], i32 2 @@ -1824,7 +1824,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK11-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4 // CHECK11-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 // CHECK11-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK11-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4 +// CHECK11-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4, !nonnull [[META12]], !align [[META13]] // CHECK11-NEXT: [[F2:%.*]] = getelementptr inbounds nuw [[STRUCT_S_0]], ptr [[TMP0]], i32 0, i32 0 // CHECK11-NEXT: [[TMP1:%.*]] = load i32, ptr [[F2]], align 4 // CHECK11-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[T]], i32 0, i32 0 @@ -1997,7 +1997,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK17-NEXT: [[TMP0:%.*]] = load i64, ptr [[VLA_ADDR]], align 8 // CHECK17-NEXT: [[TMP1:%.*]] = load i64, ptr [[VLA_ADDR3]], align 8 // CHECK17-NEXT: [[TMP2:%.*]] = load i64, ptr [[VLA_ADDR5]], align 8 -// CHECK17-NEXT: [[TMP3:%.*]] = load ptr, ptr [[VLA2_ADDR]], align 8 +// CHECK17-NEXT: [[TMP3:%.*]] = load ptr, ptr [[VLA2_ADDR]], align 8, !nonnull [[META8:![0-9]+]], !align [[META9:![0-9]+]] // CHECK17-NEXT: [[TMP4:%.*]] = load ptr, ptr [[S_ADDR]], align 8 // CHECK17-NEXT: [[TMP5:%.*]] = load ptr, ptr [[VLA1_ADDR]], align 8 // CHECK17-NEXT: [[TMP6:%.*]] = load ptr, ptr [[A_ADDR]], align 8 @@ -2031,11 +2031,11 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK17-NEXT: store i64 [[VLA2]], ptr [[VLA_ADDR3]], align 8 // CHECK17-NEXT: store i64 [[VLA4]], ptr [[VLA_ADDR5]], align 8 // CHECK17-NEXT: store ptr [[VLA26]], ptr [[VLA2_ADDR]], align 8 -// CHECK17-NEXT: [[TMP0:%.*]] = load ptr, ptr [[N_ADDR]], align 8 +// CHECK17-NEXT: [[TMP0:%.*]] = load ptr, ptr [[N_ADDR]], align 8, !nonnull [[META8]], !align [[META10:![0-9]+]] // CHECK17-NEXT: [[TMP1:%.*]] = load i64, ptr [[VLA_ADDR]], align 8 // CHECK17-NEXT: [[TMP2:%.*]] = load i64, ptr [[VLA_ADDR3]], align 8 // CHECK17-NEXT: [[TMP3:%.*]] = load i64, ptr [[VLA_ADDR5]], align 8 -// CHECK17-NEXT: [[TMP4:%.*]] = load ptr, ptr [[VLA2_ADDR]], align 8 +// CHECK17-NEXT: [[TMP4:%.*]] = load ptr, ptr [[VLA2_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] // CHECK17-NEXT: [[TMP5:%.*]] = call ptr @llvm.stacksave.p0() // CHECK17-NEXT: store ptr [[TMP5]], ptr [[SAVED_STACK]], align 8 // CHECK17-NEXT: [[TMP6:%.*]] = mul nuw i64 [[TMP2]], [[TMP3]] @@ -2235,7 +2235,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK17-NEXT: [[TMP0:%.*]] = load i64, ptr [[VLA_ADDR]], align 8 // CHECK17-NEXT: [[TMP1:%.*]] = load i64, ptr [[VLA_ADDR3]], align 8 // CHECK17-NEXT: [[TMP2:%.*]] = load i64, ptr [[VLA_ADDR5]], align 8 -// CHECK17-NEXT: [[TMP3:%.*]] = load ptr, ptr [[VLA2_ADDR]], align 8 +// CHECK17-NEXT: [[TMP3:%.*]] = load ptr, ptr [[VLA2_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] // CHECK17-NEXT: [[TMP4:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK17-NEXT: [[TMP5:%.*]] = load ptr, ptr [[VLA1_ADDR]], align 8 // CHECK17-NEXT: [[TMP6:%.*]] = load ptr, ptr [[S_ADDR]], align 8 @@ -2273,8 +2273,8 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK17-NEXT: [[TMP1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK17-NEXT: [[TMP2:%.*]] = load i64, ptr [[VLA_ADDR3]], align 8 // CHECK17-NEXT: [[TMP3:%.*]] = load i64, ptr [[VLA_ADDR5]], align 8 -// CHECK17-NEXT: [[TMP4:%.*]] = load ptr, ptr [[VLA2_ADDR]], align 8 -// CHECK17-NEXT: [[TMP5:%.*]] = load ptr, ptr [[N_ADDR]], align 8 +// CHECK17-NEXT: [[TMP4:%.*]] = load ptr, ptr [[VLA2_ADDR]], align 8, !nonnull [[META8]], !align [[META9]] +// CHECK17-NEXT: [[TMP5:%.*]] = load ptr, ptr [[N_ADDR]], align 8, !nonnull [[META8]], !align [[META10]] // CHECK17-NEXT: [[TMP6:%.*]] = call ptr @llvm.stacksave.p0() // CHECK17-NEXT: store ptr [[TMP6]], ptr [[SAVED_STACK]], align 8 // CHECK17-NEXT: [[TMP7:%.*]] = mul nuw i64 [[TMP2]], [[TMP3]] @@ -2460,7 +2460,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK19-NEXT: [[TMP0:%.*]] = load i32, ptr [[VLA_ADDR]], align 4 // CHECK19-NEXT: [[TMP1:%.*]] = load i32, ptr [[VLA_ADDR3]], align 4 // CHECK19-NEXT: [[TMP2:%.*]] = load i32, ptr [[VLA_ADDR5]], align 4 -// CHECK19-NEXT: [[TMP3:%.*]] = load ptr, ptr [[VLA2_ADDR]], align 4 +// CHECK19-NEXT: [[TMP3:%.*]] = load ptr, ptr [[VLA2_ADDR]], align 4, !nonnull [[META8:![0-9]+]], !align [[META9:![0-9]+]] // CHECK19-NEXT: [[TMP4:%.*]] = load ptr, ptr [[S_ADDR]], align 4 // CHECK19-NEXT: [[TMP5:%.*]] = load ptr, ptr [[VLA1_ADDR]], align 4 // CHECK19-NEXT: [[TMP6:%.*]] = load ptr, ptr [[A_ADDR]], align 4 @@ -2494,11 +2494,11 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK19-NEXT: store i32 [[VLA2]], ptr [[VLA_ADDR3]], align 4 // CHECK19-NEXT: store i32 [[VLA4]], ptr [[VLA_ADDR5]], align 4 // CHECK19-NEXT: store ptr [[VLA26]], ptr [[VLA2_ADDR]], align 4 -// CHECK19-NEXT: [[TMP0:%.*]] = load ptr, ptr [[N_ADDR]], align 4 +// CHECK19-NEXT: [[TMP0:%.*]] = load ptr, ptr [[N_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK19-NEXT: [[TMP1:%.*]] = load i32, ptr [[VLA_ADDR]], align 4 // CHECK19-NEXT: [[TMP2:%.*]] = load i32, ptr [[VLA_ADDR3]], align 4 // CHECK19-NEXT: [[TMP3:%.*]] = load i32, ptr [[VLA_ADDR5]], align 4 -// CHECK19-NEXT: [[TMP4:%.*]] = load ptr, ptr [[VLA2_ADDR]], align 4 +// CHECK19-NEXT: [[TMP4:%.*]] = load ptr, ptr [[VLA2_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK19-NEXT: [[TMP5:%.*]] = call ptr @llvm.stacksave.p0() // CHECK19-NEXT: store ptr [[TMP5]], ptr [[SAVED_STACK]], align 4 // CHECK19-NEXT: [[TMP6:%.*]] = mul nuw i32 [[TMP2]], [[TMP3]] @@ -2696,7 +2696,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK19-NEXT: [[TMP0:%.*]] = load i32, ptr [[VLA_ADDR]], align 4 // CHECK19-NEXT: [[TMP1:%.*]] = load i32, ptr [[VLA_ADDR3]], align 4 // CHECK19-NEXT: [[TMP2:%.*]] = load i32, ptr [[VLA_ADDR5]], align 4 -// CHECK19-NEXT: [[TMP3:%.*]] = load ptr, ptr [[VLA2_ADDR]], align 4 +// CHECK19-NEXT: [[TMP3:%.*]] = load ptr, ptr [[VLA2_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK19-NEXT: [[TMP4:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 // CHECK19-NEXT: [[TMP5:%.*]] = load ptr, ptr [[VLA1_ADDR]], align 4 // CHECK19-NEXT: [[TMP6:%.*]] = load ptr, ptr [[S_ADDR]], align 4 @@ -2734,8 +2734,8 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK19-NEXT: [[TMP1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 // CHECK19-NEXT: [[TMP2:%.*]] = load i32, ptr [[VLA_ADDR3]], align 4 // CHECK19-NEXT: [[TMP3:%.*]] = load i32, ptr [[VLA_ADDR5]], align 4 -// CHECK19-NEXT: [[TMP4:%.*]] = load ptr, ptr [[VLA2_ADDR]], align 4 -// CHECK19-NEXT: [[TMP5:%.*]] = load ptr, ptr [[N_ADDR]], align 4 +// CHECK19-NEXT: [[TMP4:%.*]] = load ptr, ptr [[VLA2_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] +// CHECK19-NEXT: [[TMP5:%.*]] = load ptr, ptr [[N_ADDR]], align 4, !nonnull [[META8]], !align [[META9]] // CHECK19-NEXT: [[TMP6:%.*]] = call ptr @llvm.stacksave.p0() // CHECK19-NEXT: store ptr [[TMP6]], ptr [[SAVED_STACK]], align 4 // CHECK19-NEXT: [[TMP7:%.*]] = mul nuw i32 [[TMP2]], [[TMP3]] diff --git a/clang/test/Preprocessor/arm-acle-6.4.c b/clang/test/Preprocessor/arm-acle-6.4.c index 2c8f4868263a6..48deba74c8ab2 100644 --- a/clang/test/Preprocessor/arm-acle-6.4.c +++ b/clang/test/Preprocessor/arm-acle-6.4.c @@ -188,6 +188,37 @@ // RUN: %clang --target=arm-arm-none-eabi -mcpu=cortex-m33 -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-M-DSP // RUN: %clang --target=arm-arm-none-eabi -march=armv8m.main+dsp -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-M-DSP +// RUN: %clang -target arm-none-linux-eabi -march=armv8m.base -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-V8M-BASE + +// CHECK-V8M-BASE-NOT: __ARM_ARCH_ISA_ARM +// CHECK-V8M-BASE-NOT: __ARM_FEATURE_DSP +// CHECK-V8M-BASE-NOT: __ARM_FEATURE_SIMD32 +// CHECK-V8M-BASE: __ARM_ARCH 8 +// CHECK-V8M-BASE: __ARM_ARCH_ISA_THUMB 1 +// CHECK-V8M-BASE: __ARM_ARCH_PROFILE 'M' +// CHECK-V8M-BASE: __ARM_FEATURE_CLZ 1 +// CHECK-V8M-BASE: __ARM_FEATURE_IDIV 1 +// CHECK-V8M-BASE: __ARM_FEATURE_LDREX 0x7 +// CHECK-V8M-BASE: __ARM_FEATURE_QBIT 1 +// CHECK-V8M-BASE: __ARM_FEATURE_SAT +// CHECK-V8M-BASE-NOT: __ARM_FEATURE_UNALIGNED + +// RUN: %clang -target arm-none-linux-eabi -march=armv8m.main -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-V8M-MAIN +// RUN: %clang -target arm-none-linux-eabi -march=armv8.1m.main -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-V8M-MAIN + +// CHECK-V8M-MAIN-NOT: __ARM_ARCH_ISA_ARM +// CHECK-V8M-MAIN-NOT: __ARM_FEATURE_DSP +// CHECK-V8M-MAIN-NOT: __ARM_FEATURE_SIMD32 +// CHECK-V8M-MAIN: __ARM_ARCH 8 +// CHECK-V8M-MAIN: __ARM_ARCH_ISA_THUMB 2 +// CHECK-V8M-MAIN: __ARM_ARCH_PROFILE 'M' +// CHECK-V8M-MAIN: __ARM_FEATURE_CLZ 1 +// CHECK-V8M-MAIN: __ARM_FEATURE_IDIV 1 +// CHECK-V8M-MAIN: __ARM_FEATURE_LDREX 0x7 +// CHECK-V8M-MAIN: __ARM_FEATURE_QBIT 1 +// CHECK-V8M-MAIN: __ARM_FEATURE_SAT 1 +// CHECK-V8M-MAIN: __ARM_FEATURE_UNALIGNED 1 + // CHECK-M-DSP: __ARM_FEATURE_DSP 1 // CHECK-M-DSP: __ARM_FEATURE_SIMD32 1 diff --git a/clang/test/Preprocessor/init-mips.c b/clang/test/Preprocessor/init-mips.c index 4fead33bd826e..125872a001bac 100644 --- a/clang/test/Preprocessor/init-mips.c +++ b/clang/test/Preprocessor/init-mips.c @@ -80,10 +80,10 @@ // MIPS32BE:#define __INTMAX_MAX__ 9223372036854775807LL // MIPS32BE:#define __INTMAX_TYPE__ long long int // MIPS32BE:#define __INTMAX_WIDTH__ 64 -// MIPS32BE:#define __INTPTR_FMTd__ "ld" -// MIPS32BE:#define __INTPTR_FMTi__ "li" -// MIPS32BE:#define __INTPTR_MAX__ 2147483647L -// MIPS32BE:#define __INTPTR_TYPE__ long int +// MIPS32BE:#define __INTPTR_FMTd__ "d" +// MIPS32BE:#define __INTPTR_FMTi__ "i" +// MIPS32BE:#define __INTPTR_MAX__ 2147483647 +// MIPS32BE:#define __INTPTR_TYPE__ int // MIPS32BE:#define __INTPTR_WIDTH__ 32 // MIPS32BE:#define __INT_FAST16_FMTd__ "hd" // MIPS32BE:#define __INT_FAST16_FMTi__ "hi" @@ -185,8 +185,8 @@ // MIPS32BE:#define __UINTMAX_MAX__ 18446744073709551615ULL // MIPS32BE:#define __UINTMAX_TYPE__ long long unsigned int // MIPS32BE:#define __UINTMAX_WIDTH__ 64 -// MIPS32BE:#define __UINTPTR_MAX__ 4294967295UL -// MIPS32BE:#define __UINTPTR_TYPE__ long unsigned int +// MIPS32BE:#define __UINTPTR_MAX__ 4294967295U +// MIPS32BE:#define __UINTPTR_TYPE__ unsigned int // MIPS32BE:#define __UINTPTR_WIDTH__ 32 // MIPS32BE:#define __UINT_FAST16_MAX__ 65535 // MIPS32BE:#define __UINT_FAST16_TYPE__ unsigned short @@ -300,10 +300,10 @@ // MIPS32EL:#define __INTMAX_MAX__ 9223372036854775807LL // MIPS32EL:#define __INTMAX_TYPE__ long long int // MIPS32EL:#define __INTMAX_WIDTH__ 64 -// MIPS32EL:#define __INTPTR_FMTd__ "ld" -// MIPS32EL:#define __INTPTR_FMTi__ "li" -// MIPS32EL:#define __INTPTR_MAX__ 2147483647L -// MIPS32EL:#define __INTPTR_TYPE__ long int +// MIPS32EL:#define __INTPTR_FMTd__ "d" +// MIPS32EL:#define __INTPTR_FMTi__ "i" +// MIPS32EL:#define __INTPTR_MAX__ 2147483647 +// MIPS32EL:#define __INTPTR_TYPE__ int // MIPS32EL:#define __INTPTR_WIDTH__ 32 // MIPS32EL:#define __INT_FAST16_FMTd__ "hd" // MIPS32EL:#define __INT_FAST16_FMTi__ "hi" @@ -402,8 +402,8 @@ // MIPS32EL:#define __UINTMAX_MAX__ 18446744073709551615ULL // MIPS32EL:#define __UINTMAX_TYPE__ long long unsigned int // MIPS32EL:#define __UINTMAX_WIDTH__ 64 -// MIPS32EL:#define __UINTPTR_MAX__ 4294967295UL -// MIPS32EL:#define __UINTPTR_TYPE__ long unsigned int +// MIPS32EL:#define __UINTPTR_MAX__ 4294967295U +// MIPS32EL:#define __UINTPTR_TYPE__ unsigned int // MIPS32EL:#define __UINTPTR_WIDTH__ 32 // MIPS32EL:#define __UINT_FAST16_MAX__ 65535 // MIPS32EL:#define __UINT_FAST16_TYPE__ unsigned short @@ -547,10 +547,10 @@ // MIPSN32BE: #define __INTMAX_MAX__ 9223372036854775807LL // MIPSN32BE: #define __INTMAX_TYPE__ long long int // MIPSN32BE: #define __INTMAX_WIDTH__ 64 -// MIPSN32BE: #define __INTPTR_FMTd__ "ld" -// MIPSN32BE: #define __INTPTR_FMTi__ "li" -// MIPSN32BE: #define __INTPTR_MAX__ 2147483647L -// MIPSN32BE: #define __INTPTR_TYPE__ long int +// MIPSN32BE: #define __INTPTR_FMTd__ "d" +// MIPSN32BE: #define __INTPTR_FMTi__ "i" +// MIPSN32BE: #define __INTPTR_MAX__ 2147483647 +// MIPSN32BE: #define __INTPTR_TYPE__ int // MIPSN32BE: #define __INTPTR_WIDTH__ 32 // MIPSN32BE: #define __INT_FAST16_FMTd__ "hd" // MIPSN32BE: #define __INT_FAST16_FMTi__ "hi" @@ -684,12 +684,12 @@ // MIPSN32BE: #define __UINTMAX_MAX__ 18446744073709551615ULL // MIPSN32BE: #define __UINTMAX_TYPE__ long long unsigned int // MIPSN32BE: #define __UINTMAX_WIDTH__ 64 -// MIPSN32BE: #define __UINTPTR_FMTX__ "lX" -// MIPSN32BE: #define __UINTPTR_FMTo__ "lo" -// MIPSN32BE: #define __UINTPTR_FMTu__ "lu" -// MIPSN32BE: #define __UINTPTR_FMTx__ "lx" -// MIPSN32BE: #define __UINTPTR_MAX__ 4294967295UL -// MIPSN32BE: #define __UINTPTR_TYPE__ long unsigned int +// MIPSN32BE: #define __UINTPTR_FMTX__ "X" +// MIPSN32BE: #define __UINTPTR_FMTo__ "o" +// MIPSN32BE: #define __UINTPTR_FMTu__ "u" +// MIPSN32BE: #define __UINTPTR_FMTx__ "x" +// MIPSN32BE: #define __UINTPTR_MAX__ 4294967295U +// MIPSN32BE: #define __UINTPTR_TYPE__ unsigned int // MIPSN32BE: #define __UINTPTR_WIDTH__ 32 // MIPSN32BE: #define __UINT_FAST16_FMTX__ "hX" // MIPSN32BE: #define __UINT_FAST16_FMTo__ "ho" @@ -864,10 +864,10 @@ // MIPSN32EL: #define __INTMAX_MAX__ 9223372036854775807LL // MIPSN32EL: #define __INTMAX_TYPE__ long long int // MIPSN32EL: #define __INTMAX_WIDTH__ 64 -// MIPSN32EL: #define __INTPTR_FMTd__ "ld" -// MIPSN32EL: #define __INTPTR_FMTi__ "li" -// MIPSN32EL: #define __INTPTR_MAX__ 2147483647L -// MIPSN32EL: #define __INTPTR_TYPE__ long int +// MIPSN32EL: #define __INTPTR_FMTd__ "d" +// MIPSN32EL: #define __INTPTR_FMTi__ "i" +// MIPSN32EL: #define __INTPTR_MAX__ 2147483647 +// MIPSN32EL: #define __INTPTR_TYPE__ int // MIPSN32EL: #define __INTPTR_WIDTH__ 32 // MIPSN32EL: #define __INT_FAST16_FMTd__ "hd" // MIPSN32EL: #define __INT_FAST16_FMTi__ "hi" @@ -1001,12 +1001,12 @@ // MIPSN32EL: #define __UINTMAX_MAX__ 18446744073709551615ULL // MIPSN32EL: #define __UINTMAX_TYPE__ long long unsigned int // MIPSN32EL: #define __UINTMAX_WIDTH__ 64 -// MIPSN32EL: #define __UINTPTR_FMTX__ "lX" -// MIPSN32EL: #define __UINTPTR_FMTo__ "lo" -// MIPSN32EL: #define __UINTPTR_FMTu__ "lu" -// MIPSN32EL: #define __UINTPTR_FMTx__ "lx" -// MIPSN32EL: #define __UINTPTR_MAX__ 4294967295UL -// MIPSN32EL: #define __UINTPTR_TYPE__ long unsigned int +// MIPSN32EL: #define __UINTPTR_FMTX__ "X" +// MIPSN32EL: #define __UINTPTR_FMTo__ "o" +// MIPSN32EL: #define __UINTPTR_FMTu__ "u" +// MIPSN32EL: #define __UINTPTR_FMTx__ "x" +// MIPSN32EL: #define __UINTPTR_MAX__ 4294967295U +// MIPSN32EL: #define __UINTPTR_TYPE__ unsigned int // MIPSN32EL: #define __UINTPTR_WIDTH__ 32 // MIPSN32EL: #define __UINT_FAST16_FMTX__ "hX" // MIPSN32EL: #define __UINT_FAST16_FMTo__ "ho" diff --git a/clang/test/Preprocessor/openacc.c b/clang/test/Preprocessor/openacc.c index be7052f00e0ce..283baa6c2fe4b 100644 --- a/clang/test/Preprocessor/openacc.c +++ b/clang/test/Preprocessor/openacc.c @@ -1,13 +1,9 @@ // RUN: %clang_cc1 -E -fopenacc %s | FileCheck %s --check-prefix=DEFAULT -// RUN: %clang_cc1 -E -fopenacc -fexperimental-openacc-macro-override 202211 %s | FileCheck %s --check-prefix=OVERRIDE -// DEFAULT: OpenACC:1: -// OVERRIDE: OpenACC:202211: +// DEFAULT: OpenACC:202506: OpenACC:_OPENACC: // RUN: %clang_cc1 -E -dM -fopenacc %s | FileCheck %s --check-prefix=MACRO_PRINT_DEF -// RUN: %clang_cc1 -E -dM -fopenacc -fexperimental-openacc-macro-override 202211 %s | FileCheck %s --check-prefix=MACRO_PRINT_OVR -// MACRO_PRINT_DEF: #define _OPENACC 1 -// MACRO_PRINT_OVR: #define _OPENACC 202211 +// MACRO_PRINT_DEF: #define _OPENACC 202506 diff --git a/clang/test/Preprocessor/pragma-pushpop-macro-diag.c b/clang/test/Preprocessor/pragma-pushpop-macro-diag.c new file mode 100644 index 0000000000000..293cb828d832e --- /dev/null +++ b/clang/test/Preprocessor/pragma-pushpop-macro-diag.c @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -fms-extensions %s -fsyntax-only -verify + +#pragma push_macro("") // expected-warning {{'#pragma push_macro' expected a non-empty string}} +#pragma pop_macro("") // expected-warning {{'#pragma pop_macro' expected a non-empty string}} diff --git a/clang/test/Preprocessor/pragma-pushpop-macro.c b/clang/test/Preprocessor/pragma-pushpop-macro.c index 0aee074c55c77..238e3ed5eddb3 100644 --- a/clang/test/Preprocessor/pragma-pushpop-macro.c +++ b/clang/test/Preprocessor/pragma-pushpop-macro.c @@ -56,3 +56,6 @@ int P; // CHECK: int pmy2 = 4 // CHECK: int Q; // CHECK: int P; + +#pragma push_macro("") +#pragma pop_macro("") diff --git a/clang/test/Preprocessor/stdint.c b/clang/test/Preprocessor/stdint.c index 899ff59bf0b6a..9f982a3a94fd6 100644 --- a/clang/test/Preprocessor/stdint.c +++ b/clang/test/Preprocessor/stdint.c @@ -350,8 +350,8 @@ // MIPS:typedef int8_t int_fast8_t; // MIPS:typedef uint8_t uint_fast8_t; // -// MIPS:typedef long int intptr_t; -// MIPS:typedef long unsigned int uintptr_t; +// MIPS:typedef int intptr_t; +// MIPS:typedef unsigned int uintptr_t; // // MIPS:typedef long long int intmax_t; // MIPS:typedef long long unsigned int uintmax_t; @@ -396,9 +396,9 @@ // MIPS:INT_FAST64_MAX_ 9223372036854775807LL // MIPS:UINT_FAST64_MAX_ 18446744073709551615ULL // -// MIPS:INTPTR_MIN_ (-2147483647L -1) -// MIPS:INTPTR_MAX_ 2147483647L -// MIPS:UINTPTR_MAX_ 4294967295UL +// MIPS:INTPTR_MIN_ (-2147483647 -1) +// MIPS:INTPTR_MAX_ 2147483647 +// MIPS:UINTPTR_MAX_ 4294967295U // MIPS:PTRDIFF_MIN_ (-2147483647 -1) // MIPS:PTRDIFF_MAX_ 2147483647 // MIPS:SIZE_MAX_ 4294967295U diff --git a/clang/test/Sema/attr-nonblocking-sema.cpp b/clang/test/Sema/attr-nonblocking-sema.cpp index f13cc783dfc33..c8fb40693eec0 100644 --- a/clang/test/Sema/attr-nonblocking-sema.cpp +++ b/clang/test/Sema/attr-nonblocking-sema.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -fblocks -fcxx-exceptions -verify -Wfunction-effects %s -// RUN: %clang_cc1 -fsyntax-only -fblocks -verify -x c -std=c23 -Wfunction-effects %s +// RUN: %clang_cc1 -fsyntax-only -fblocks -fcxx-exceptions -verify -Wfunction-effects -Wfunction-effect-redeclarations %s +// RUN: %clang_cc1 -fsyntax-only -fblocks -verify -x c -std=c23 -Wfunction-effects -Wfunction-effect-redeclarations %s #if !__has_attribute(nonblocking) #error "the 'nonblocking' attribute is not available" @@ -127,29 +127,35 @@ void type_conversions_2() #endif // --- VIRTUAL METHODS --- -// Attributes propagate to overridden methods, so no diagnostics except for conflicts. +// Attributes propagate to overridden methods. // Check this in the syntax tests too. #ifdef __cplusplus struct Base { virtual void f1(); - virtual void nonblocking() noexcept [[clang::nonblocking]]; - virtual void nonallocating() noexcept [[clang::nonallocating]]; + virtual void nonblocking() noexcept [[clang::nonblocking]]; // expected-note {{overridden virtual function is here}} + virtual void nonallocating() noexcept [[clang::nonallocating]]; // expected-note {{overridden virtual function is here}} virtual void f2() [[clang::nonallocating]]; // expected-note {{previous declaration is here}} + virtual void f3() [[clang::nonblocking]]; // expected-note {{overridden virtual function is here}} }; struct Derived : public Base { void f1() [[clang::nonblocking]] override; - void nonblocking() noexcept override; - void nonallocating() noexcept override; + void nonblocking() noexcept override; // expected-warning {{overriding function is missing 'nonblocking' attribute from base declaration}} + void nonallocating() noexcept override; // expected-warning {{overriding function is missing 'nonallocating' attribute from base declaration}} void f2() [[clang::allocating]] override; // expected-warning {{effects conflict when merging declarations; kept 'allocating', discarded 'nonallocating'}} }; + +template +struct TDerived : public Base { + void f3() [[clang::nonblocking(B)]] override; // expected-warning {{attribute 'nonblocking' on overriding function conflicts with base declaration}} +}; #endif // __cplusplus // --- REDECLARATIONS --- void f2(); void f2() [[clang::nonblocking]]; // expected-note {{previous declaration is here}} -void f2(); // expected-warning {{attribute 'nonblocking' on function does not match previous declaration}} +void f2(); // expected-warning {{redeclaration is missing 'nonblocking' attribute from previous declaration}} // Note: we verify that the attribute is actually seen during the constraints tests. void f3() [[clang::blocking]]; // expected-note {{previous declaration is here}} diff --git a/clang/test/Sema/builtins-elementwise-math.c b/clang/test/Sema/builtins-elementwise-math.c index 01057b3f8d083..8548d3be8c44a 100644 --- a/clang/test/Sema/builtins-elementwise-math.c +++ b/clang/test/Sema/builtins-elementwise-math.c @@ -386,6 +386,96 @@ void test_builtin_elementwise_minimum(int i, short s, float f, double d, float4 // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was '_Complex float')}} } +void test_builtin_elementwise_maximumnum(int i, short s, float f, double d, float4 fv, double4 dv, int3 iv, unsigned3 uv, int *p) { + i = __builtin_elementwise_maximumnum(p, d); + // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int *')}} + + struct Foo foo = __builtin_elementwise_maximumnum(d, d); + // expected-error@-1 {{initializing 'struct Foo' with an expression of incompatible type 'double'}} + + i = __builtin_elementwise_maximumnum(i); + // expected-error@-1 {{too few arguments to function call, expected 2, have 1}} + + i = __builtin_elementwise_maximumnum(); + // expected-error@-1 {{too few arguments to function call, expected 2, have 0}} + + i = __builtin_elementwise_maximumnum(i, i, i); + // expected-error@-1 {{too many arguments to function call, expected 2, have 3}} + + i = __builtin_elementwise_maximumnum(fv, iv); + // expected-error@-1 {{arguments are of different types ('float4' (vector of 4 'float' values) vs 'int3' (vector of 3 'int' values))}} + + i = __builtin_elementwise_maximumnum(uv, iv); + // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'unsigned3' (vector of 3 'unsigned int' values))}} + + dv = __builtin_elementwise_maximumnum(fv, dv); + // expected-error@-1 {{arguments are of different types ('float4' (vector of 4 'float' values) vs 'double4' (vector of 4 'double' values))}} + + d = __builtin_elementwise_maximumnum(f, d); + // expected-error@-1 {{arguments are of different types ('float' vs 'double')}} + + fv = __builtin_elementwise_maximumnum(fv, fv); + + i = __builtin_elementwise_maximumnum(iv, iv); + // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int3' (vector of 3 'int' values))}} + + i = __builtin_elementwise_maximumnum(i, i); + // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int')}} + + int A[10]; + A = __builtin_elementwise_maximumnum(A, A); + // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int *')}} + + _Complex float c1, c2; + c1 = __builtin_elementwise_maximumnum(c1, c2); + // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was '_Complex float')}} +} + +void test_builtin_elementwise_minimumnum(int i, short s, float f, double d, float4 fv, double4 dv, int3 iv, unsigned3 uv, int *p) { + i = __builtin_elementwise_minimumnum(p, d); + // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int *')}} + + struct Foo foo = __builtin_elementwise_minimumnum(d, d); + // expected-error@-1 {{initializing 'struct Foo' with an expression of incompatible type 'double'}} + + i = __builtin_elementwise_minimumnum(i); + // expected-error@-1 {{too few arguments to function call, expected 2, have 1}} + + i = __builtin_elementwise_minimumnum(); + // expected-error@-1 {{too few arguments to function call, expected 2, have 0}} + + i = __builtin_elementwise_minimumnum(i, i, i); + // expected-error@-1 {{too many arguments to function call, expected 2, have 3}} + + i = __builtin_elementwise_minimumnum(fv, iv); + // expected-error@-1 {{arguments are of different types ('float4' (vector of 4 'float' values) vs 'int3' (vector of 3 'int' values))}} + + i = __builtin_elementwise_minimumnum(uv, iv); + // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'unsigned3' (vector of 3 'unsigned int' values))}} + + dv = __builtin_elementwise_minimumnum(fv, dv); + // expected-error@-1 {{arguments are of different types ('float4' (vector of 4 'float' values) vs 'double4' (vector of 4 'double' values))}} + + d = __builtin_elementwise_minimumnum(f, d); + // expected-error@-1 {{arguments are of different types ('float' vs 'double')}} + + fv = __builtin_elementwise_minimumnum(fv, fv); + + i = __builtin_elementwise_minimumnum(iv, iv); + // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int3' (vector of 3 'int' values))}} + + i = __builtin_elementwise_minimumnum(i, i); + // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int')}} + + int A[10]; + A = __builtin_elementwise_minimumnum(A, A); + // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int *')}} + + _Complex float c1, c2; + c1 = __builtin_elementwise_minimumnum(c1, c2); + // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was '_Complex float')}} +} + void test_builtin_elementwise_bitreverse(int i, float f, double d, float4 v, int3 iv, unsigned u, unsigned4 uv) { struct Foo s = __builtin_elementwise_bitreverse(i); diff --git a/clang/test/Sema/const-eval.c b/clang/test/Sema/const-eval.c index e358aceaad5a4..11cc7fbc0feb3 100644 --- a/clang/test/Sema/const-eval.c +++ b/clang/test/Sema/const-eval.c @@ -32,7 +32,7 @@ void f(void) _Complex float g16 = (1.0f + 1.0fi); // ?: in constant expressions. -int g17[(3?:1) - 2]; +int g17[(3?:1) - 2]; EVAL_EXPR(18, ((int)((void*)10 + 10)) == 20 ? 1 : -1); @@ -150,3 +150,7 @@ struct PR35214_X { int PR35214_x; int PR35214_y = ((struct PR35214_X *)&PR35214_x)->arr[1]; // expected-error {{not a compile-time constant}} int *PR35214_z = &((struct PR35214_X *)&PR35214_x)->arr[1]; // ok, &PR35214_x + 2 + + +int * GH149500_p = &(*(int *)0x400); +static const void *GH149500_q = &(*(const struct sysrq_key_op *)0); diff --git a/clang/test/Sema/diagnose_if.c b/clang/test/Sema/diagnose_if.c index e9b8497d5ca4e..a4cf43e9c869f 100644 --- a/clang/test/Sema/diagnose_if.c +++ b/clang/test/Sema/diagnose_if.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -verify -fno-builtin +// RUN: %clang_cc1 %s -verify -fno-builtin -fexperimental-new-constant-interpreter #define _diagnose_if(...) __attribute__((diagnose_if(__VA_ARGS__))) diff --git a/clang/test/Sema/dllexport.c b/clang/test/Sema/dllexport.c index 3f911fb095c0f..5f6ff36e290e9 100644 --- a/clang/test/Sema/dllexport.c +++ b/clang/test/Sema/dllexport.c @@ -2,6 +2,10 @@ // RUN: %clang_cc1 -triple x86_64-win32 -fsyntax-only -fms-extensions -verify -std=c11 %s // RUN: %clang_cc1 -triple i686-mingw32 -fsyntax-only -fms-extensions -verify -std=c11 %s // RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -fms-extensions -verify -std=c99 %s +// RUN: %clang_cc1 -triple i686-windows-itanium -fsyntax-only -fms-extensions -verify -std=c99 %s +// RUN: %clang_cc1 -triple x86_64-windows-itanium -fsyntax-only -fms-extensions -verify -std=c11 %s +// RUN: %clang_cc1 -triple x86_64-sie-ps5 -fsyntax-only -fms-extensions -verify -std=c99 %s +// RUN: %clang_cc1 -triple x86_64-sie-ps5 -fsyntax-only -fms-extensions -verify -std=c11 %s // Invalid usage. __declspec(dllexport) typedef int typedef1; diff --git a/clang/test/Sema/format-strings-fixit-ssize_t.c b/clang/test/Sema/format-strings-fixit-ssize_t.c index 2c83db0b66362..96806517b80f2 100644 --- a/clang/test/Sema/format-strings-fixit-ssize_t.c +++ b/clang/test/Sema/format-strings-fixit-ssize_t.c @@ -11,8 +11,8 @@ int printf(char const *, ...); int scanf(const char *, ...); +typedef long ssize_t; void test(void) { - typedef signed long int ssize_t; printf("%f", (ssize_t) 42); ssize_t s; scanf("%f", &s); diff --git a/clang/test/Sema/format-strings-scanf.c b/clang/test/Sema/format-strings-scanf.c index eb5b8ec36bf7a..d1f694f3595cf 100644 --- a/clang/test/Sema/format-strings-scanf.c +++ b/clang/test/Sema/format-strings-scanf.c @@ -210,13 +210,13 @@ void test_size_types(void) { scanf("%zd", &s); // No warning. double d2 = 0.; - scanf("%zd", &d2); // expected-warning-re{{format specifies type 'ssize_t *' (aka '{{.+}}') but the argument has type 'double *'}} + scanf("%zd", &d2); // expected-warning-re{{format specifies type 'signed size_t *' (aka '{{.+}}') but the argument has type 'double *'}} ssize_t sn = 0; scanf("%zn", &sn); // No warning. double d3 = 0.; - scanf("%zn", &d3); // expected-warning-re{{format specifies type 'ssize_t *' (aka '{{.+}}') but the argument has type 'double *'}} + scanf("%zn", &d3); // expected-warning-re{{format specifies type 'signed size_t *' (aka '{{.+}}') but the argument has type 'double *'}} } void test_ptrdiff_t_types(void) { diff --git a/clang/test/Sema/format-strings-size_t.c b/clang/test/Sema/format-strings-size_t.c index 5058a762183d3..19e3ac9e6ecd9 100644 --- a/clang/test/Sema/format-strings-size_t.c +++ b/clang/test/Sema/format-strings-size_t.c @@ -2,10 +2,14 @@ int printf(char const *, ...); +#include + void test(void) { // size_t + printf("%zu", (size_t)0); // no-warning + printf("%zu", sizeof(int)); // no-warning + printf("%zu", (size_t)0 + sizeof(int)); // no-warning printf("%zu", (double)42); // expected-warning {{format specifies type 'size_t' (aka 'unsigned long') but the argument has type 'double'}} - // intmax_t / uintmax_t printf("%jd", (double)42); // expected-warning {{format specifies type 'intmax_t' (aka 'long') but the argument has type 'double'}} printf("%ju", (double)42); // expected-warning {{format specifies type 'uintmax_t' (aka 'unsigned long') but the argument has type 'double'}} diff --git a/clang/test/Sema/matrix-type-builtins.c b/clang/test/Sema/matrix-type-builtins.c index b92f3ce6a3e8c..77e3b8a4287ed 100644 --- a/clang/test/Sema/matrix-type-builtins.c +++ b/clang/test/Sema/matrix-type-builtins.c @@ -73,13 +73,13 @@ void column_major_load(float *p1, int *p2, _Bool *p3, struct Foo *p4) { 10, // expected-error {{1st argument must be a pointer to a valid matrix element type}} 1ull << 21, // expected-error {{row dimension is outside the allowed range [1, 1048575]}} 1ull << 21, // expected-error {{column dimension is outside the allowed range [1, 1048575]}} - ""); // expected-error {{incompatible pointer to integer conversion casting 'char[1]' to type 'unsigned long'}} + ""); // expected-error {{incompatible pointer to integer conversion casting 'char[1]' to type '__size_t' (aka 'unsigned long')}} sx5x10_t a13 = __builtin_matrix_column_major_load( 10, // expected-error {{1st argument must be a pointer to a valid matrix element type}} - *p4, // expected-error {{casting 'struct Foo' to incompatible type 'unsigned long'}} + *p4, // expected-error {{casting 'struct Foo' to incompatible type '__size_t' (aka 'unsigned long')}} "", // expected-error {{column argument must be a constant unsigned integer expression}} - // expected-error@-1 {{incompatible pointer to integer conversion casting 'char[1]' to type 'unsigned long'}} + // expected-error@-1 {{incompatible pointer to integer conversion casting 'char[1]' to type '__size_t' (aka 'unsigned long')}} 10); } @@ -96,7 +96,7 @@ void column_major_store(sx5x10_t *m1, ix3x2_t *m2, float *p1, int *p2, struct Fo __builtin_matrix_column_major_store( "", // expected-error {{1st argument must be a matrix}} 10, // expected-error {{2nd argument must be a pointer to a valid matrix element type}} - *p3); // expected-error {{casting 'struct Foo' to incompatible type 'unsigned long'}} + *p3); // expected-error {{casting 'struct Foo' to incompatible type '__size_t' (aka 'unsigned long')}} __builtin_matrix_column_major_store( *m1, diff --git a/clang/test/Sema/ptrauth-atomic-ops.c b/clang/test/Sema/ptrauth-atomic-ops.c index ccb9a1abcc14d..8872090d83b8d 100644 --- a/clang/test/Sema/ptrauth-atomic-ops.c +++ b/clang/test/Sema/ptrauth-atomic-ops.c @@ -54,7 +54,7 @@ void f() { __c11_atomic_exchange(ATOMIZE(j), ATOMIZE(non_addr_discriminatedauthenticated_ptr), memory_order_seq_cst); // expected-error@-1 {{incompatible pointer to integer conversion passing 'volatile __ptrauth(2,0,200) _Atomic(int *) *' to parameter of type 'typeof (j)' (aka 'int')}} __c11_atomic_fetch_add(ATOMIZE(non_addr_discriminatedauthenticated_ptr), ATOMIZE(j), memory_order_seq_cst); - // expected-error@-1 {{incompatible pointer to integer conversion passing 'volatile _Atomic(typeof (j)) *' to parameter of type 'long'}} + // expected-error@-1 {{incompatible pointer to integer conversion passing 'volatile _Atomic(typeof (j)) *' to parameter of type '__ptrdiff_t'}} __c11_atomic_fetch_and(ATOMIZE(j), ATOMIZE(non_addr_discriminatedauthenticated_ptr), memory_order_seq_cst); // expected-error@-1 {{incompatible pointer to integer conversion passing 'volatile __ptrauth(2,0,200) _Atomic(int *) *' to parameter of type 'typeof (j)' (aka 'int')}} diff --git a/clang/test/Sema/ptrauth.c b/clang/test/Sema/ptrauth.c index e3932615c2962..b4e5214a7cb50 100644 --- a/clang/test/Sema/ptrauth.c +++ b/clang/test/Sema/ptrauth.c @@ -57,7 +57,7 @@ void test_string_discriminator(const char *str) { __builtin_ptrauth_string_discriminator(str); // expected-error {{argument must be a string literal}} __builtin_ptrauth_string_discriminator(L"wide test"); // expected-error {{argument must be a string literal}} expected-warning {{incompatible pointer types passing 'int[10]' to parameter of type 'const char *'}} - void *mismatch = __builtin_ptrauth_string_discriminator("test string"); // expected-error {{incompatible integer to pointer conversion initializing 'void *' with an expression of type 'unsigned long'}} + void *mismatch = __builtin_ptrauth_string_discriminator("test string"); // expected-error {{incompatible integer to pointer conversion initializing 'void *' with an expression of type '__size_t'}} } diff --git a/clang/test/Sema/warn-fortify-source.c b/clang/test/Sema/warn-fortify-source.c index f48ea0907c657..216878c0836d8 100644 --- a/clang/test/Sema/warn-fortify-source.c +++ b/clang/test/Sema/warn-fortify-source.c @@ -3,6 +3,11 @@ // RUN: %clang_cc1 -xc++ -triple x86_64-apple-macosx10.14.0 %s -verify // RUN: %clang_cc1 -xc++ -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_BUILTINS +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.14.0 %s -verify -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_BUILTINS -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -xc++ -triple x86_64-apple-macosx10.14.0 %s -verify -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -xc++ -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_BUILTINS -fexperimental-new-constant-interpreter + typedef unsigned long size_t; #ifdef __cplusplus diff --git a/clang/test/Sema/warn-lifetime-safety-dataflow.cpp b/clang/test/Sema/warn-lifetime-safety-dataflow.cpp index 38dfdb98f08fc..2b934ac23b92d 100644 --- a/clang/test/Sema/warn-lifetime-safety-dataflow.cpp +++ b/clang/test/Sema/warn-lifetime-safety-dataflow.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -mllvm -debug-only=LifetimeFacts,LifetimeDataflow -Wexperimental-lifetime-safety %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -fexperimental-lifetime-safety -mllvm -debug-only=LifetimeFacts -Wexperimental-lifetime-safety %s 2>&1 | FileCheck %s // REQUIRES: asserts struct MyObj { @@ -19,10 +19,6 @@ MyObj* return_local_addr() { // CHECK: ReturnOfOrigin (OriginID: [[O_RET_VAL]]) // CHECK: Expire (LoanID: [[L_X]]) } -// CHECK: Dataflow results: -// CHECK-DAG: Origin [[O_ADDR_X]] contains Loan [[L_X]] -// CHECK-DAG: Origin [[O_P]] contains Loan [[L_X]] -// CHECK-DAG: Origin [[O_RET_VAL]] contains Loan [[L_X]] // Pointer Assignment and Return @@ -47,15 +43,6 @@ MyObj* assign_and_return_local_addr() { // CHECK: ReturnOfOrigin (OriginID: [[O_PTR2_RVAL_2]]) // CHECK: Expire (LoanID: [[L_Y]]) } -// CHECK: Dataflow results: -// CHECK-DAG: Origin [[O_ADDR_Y]] contains Loan [[L_Y]] -// CHECK-DAG: Origin [[O_PTR1]] contains Loan [[L_Y]] -// CHECK-DAG: Origin [[O_PTR2]] contains Loan [[L_Y]] -// CHECK-DAG: Origin [[O_PTR1_RVAL]] contains Loan [[L_Y]] -// CHECK-DAG: Origin [[O_PTR1_RVAL_2]] contains Loan [[L_Y]] -// CHECK-DAG: Origin [[O_PTR2_RVAL]] contains Loan [[L_Y]] -// CHECK-DAG: Origin [[O_PTR2_RVAL_2]] contains Loan [[L_Y]] - // Return of Non-Pointer Type // CHECK-LABEL: Function: return_int_val @@ -65,8 +52,6 @@ int return_int_val() { return x; } // CHECK-NEXT: End of Block -// CHECK: Dataflow results: -// CHECK: // Loan Expiration (Automatic Variable, C++) @@ -79,9 +64,6 @@ void loan_expires_cpp() { // CHECK: AssignOrigin (DestID: [[O_POBJ:[0-9]+]], SrcID: [[O_ADDR_OBJ]]) // CHECK: Expire (LoanID: [[L_OBJ]]) } -// CHECK: Dataflow results: -// CHECK-DAG: Origin [[O_ADDR_OBJ]] contains Loan [[L_OBJ]] -// CHECK-DAG: Origin [[O_POBJ]] contains Loan [[L_OBJ]] // FIXME: No expire for Trivial Destructors @@ -96,10 +78,6 @@ void loan_expires_trivial() { // CHECK-NEXT: End of Block // FIXME: Add check for Expire once trivial destructors are handled for expiration. } -// CHECK: Dataflow results: -// CHECK-DAG: Origin [[O_ADDR_TRIVIAL_OBJ]] contains Loan [[L_TRIVIAL_OBJ]] -// CHECK-DAG: Origin [[O_PTOBJ]] contains Loan [[L_TRIVIAL_OBJ]] - // CHECK-LABEL: Function: conditional void conditional(bool condition) { @@ -119,13 +97,6 @@ void conditional(bool condition) { // CHECK: AssignOrigin (DestID: [[O_P_RVAL:[0-9]+]], SrcID: [[O_P]]) // CHECK: AssignOrigin (DestID: [[O_Q:[0-9]+]], SrcID: [[O_P_RVAL]]) } -// CHECK: Dataflow results: -// CHECK-DAG: Origin [[O_ADDR_A]] contains Loan [[L_A]] -// CHECK-DAG: Origin [[O_ADDR_B]] contains Loan [[L_B]] -// CHECK-DAG: Origin [[O_P]] contains Loan [[L_A]] -// CHECK-DAG: Origin [[O_P]] contains Loan [[L_B]] -// CHECK-DAG: Origin [[O_Q]] contains Loan [[L_A]] -// CHECK-DAG: Origin [[O_Q]] contains Loan [[L_B]] // CHECK-LABEL: Function: pointers_in_a_cycle @@ -161,25 +132,6 @@ void pointers_in_a_cycle(bool condition) { // CHECK: AssignOrigin (DestID: [[O_P3]], SrcID: [[O_TEMP_RVAL]]) } } -// At the end of the analysis, the origins for the pointers involved in the cycle -// (p1, p2, p3, temp) should all contain the loans from v1, v2, and v3 at the fixed point. -// CHECK: Dataflow results: -// CHECK-DAG: Origin [[O_P1]] contains Loan [[L_V1]] -// CHECK-DAG: Origin [[O_P1]] contains Loan [[L_V2]] -// CHECK-DAG: Origin [[O_P1]] contains Loan [[L_V3]] -// CHECK-DAG: Origin [[O_P2]] contains Loan [[L_V1]] -// CHECK-DAG: Origin [[O_P2]] contains Loan [[L_V2]] -// CHECK-DAG: Origin [[O_P2]] contains Loan [[L_V3]] -// CHECK-DAG: Origin [[O_P3]] contains Loan [[L_V1]] -// CHECK-DAG: Origin [[O_P3]] contains Loan [[L_V2]] -// CHECK-DAG: Origin [[O_P3]] contains Loan [[L_V3]] -// CHECK-DAG: Origin [[O_TEMP]] contains Loan [[L_V1]] -// CHECK-DAG: Origin [[O_TEMP]] contains Loan [[L_V2]] -// CHECK-DAG: Origin [[O_TEMP]] contains Loan [[L_V3]] -// CHECK-DAG: Origin [[O_ADDR_V1]] contains Loan [[L_V1]] -// CHECK-DAG: Origin [[O_ADDR_V2]] contains Loan [[L_V2]] -// CHECK-DAG: Origin [[O_ADDR_V3]] contains Loan [[L_V3]] - // CHECK-LABEL: Function: overwrite_origin void overwrite_origin() { @@ -195,10 +147,6 @@ void overwrite_origin() { // CHECK: Expire (LoanID: [[L_S2]]) // CHECK: Expire (LoanID: [[L_S1]]) } -// CHECK: Dataflow results: -// CHECK: Origin [[O_P]] contains Loan [[L_S2]] -// CHECK-NOT: Origin [[O_P]] contains Loan [[L_S1]] - // CHECK-LABEL: Function: reassign_to_null void reassign_to_null() { @@ -213,8 +161,6 @@ void reassign_to_null() { } // FIXME: Have a better representation for nullptr than just an empty origin. // It should be a separate loan and origin kind. -// CHECK: Dataflow results: -// CHECK: Origin [[O_P]] contains no loans // CHECK-LABEL: Function: reassign_in_if @@ -235,11 +181,6 @@ void reassign_in_if(bool condition) { // CHECK: Expire (LoanID: [[L_S2]]) // CHECK: Expire (LoanID: [[L_S1]]) } -// CHECK: Dataflow results: -// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S1]] -// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S2]] -// CHECK-DAG: Origin [[O_ADDR_S1]] contains Loan [[L_S1]] -// CHECK-DAG: Origin [[O_ADDR_S2]] contains Loan [[L_S2]] // CHECK-LABEL: Function: assign_in_switch @@ -276,14 +217,6 @@ void assign_in_switch(int mode) { // CHECK-DAG: Expire (LoanID: [[L_S2]]) // CHECK-DAG: Expire (LoanID: [[L_S1]]) } -// CHECK: Dataflow results: -// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S1]] -// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S2]] -// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S3]] -// CHECK-DAG: Origin [[O_ADDR_S1]] contains Loan [[L_S1]] -// CHECK-DAG: Origin [[O_ADDR_S2]] contains Loan [[L_S2]] -// CHECK-DAG: Origin [[O_ADDR_S3]] contains Loan [[L_S3]] - // CHECK-LABEL: Function: loan_in_loop void loan_in_loop(bool condition) { @@ -299,10 +232,6 @@ void loan_in_loop(bool condition) { // CHECK: Expire (LoanID: [[L_INNER]]) } } -// CHECK: Dataflow results: -// CHECK-DAG: Origin [[O_P]] contains Loan [[L_INNER]] -// CHECK-DAG: Origin [[O_ADDR_INNER]] contains Loan [[L_INNER]] - // CHECK-LABEL: Function: loop_with_break void loop_with_break(int count) { @@ -326,13 +255,6 @@ void loop_with_break(int count) { // CHECK: Expire (LoanID: [[L_S1]]) } -// CHECK-LABEL: Dataflow results: -// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S1]] -// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S2]] -// CHECK-DAG: Origin [[O_ADDR_S1]] contains Loan [[L_S1]] -// CHECK-DAG: Origin [[O_ADDR_S2]] contains Loan [[L_S2]] - - // CHECK-LABEL: Function: nested_scopes void nested_scopes() { MyObj* p = nullptr; @@ -355,13 +277,6 @@ void nested_scopes() { // CHECK: Expire (LoanID: [[L_OUTER]]) } -// CHECK-LABEL: Dataflow results: -// CHECK-DAG: Origin [[O_P]] contains Loan [[L_INNER]] -// CHECK-DAG: Origin [[O_ADDR_INNER]] contains Loan [[L_INNER]] -// CHECK-DAG: Origin [[O_ADDR_OUTER]] contains Loan [[L_OUTER]] -// CHECK-NOT: Origin [[O_P]] contains Loan [[L_OUTER]] - - // CHECK-LABEL: Function: pointer_indirection void pointer_indirection() { int a; diff --git a/clang/test/SemaCXX/attr-target-clones-riscv.cpp b/clang/test/SemaCXX/attr-target-clones-riscv.cpp index 102bb4b9b3d2b..7648284f80c48 100644 --- a/clang/test/SemaCXX/attr-target-clones-riscv.cpp +++ b/clang/test/SemaCXX/attr-target-clones-riscv.cpp @@ -9,6 +9,9 @@ void __attribute__((target_clones("default", "mtune=sifive-u74"))) mtune() {} // expected-warning@+1 {{version list contains duplicate entries}} void __attribute__((target_clones("default", "arch=+c", "arch=+c"))) dupVersion() {} +// expected-warning@+1 {{version list contains duplicate entries}} +void __attribute__((target_clones(" default", "default "))) dupDefault() {} + // expected-warning@+1 {{unsupported '' in the 'target_clones' attribute string; 'target_clones' attribute ignored}} void __attribute__((target_clones("default", ""))) emptyVersion() {} diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index c390fee1c38d9..5ecb8c607f59a 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -1413,8 +1413,8 @@ namespace ComplexConstexpr { static_assert(t2p[2] == 0.0, ""); // expected-error {{constant expr}} expected-note {{one-past-the-end pointer}} static_assert(t2p[3] == 0.0, ""); // expected-error {{constant expr}} expected-note {{cannot refer to element 3 of array of 2 elements}} constexpr _Complex float *p = 0; // expected-warning {{'_Complex' is a C99 extension}} - constexpr float pr = __real *p; // expected-error {{constant expr}} expected-note {{cannot access real component of null}} - constexpr float pi = __imag *p; // expected-error {{constant expr}} expected-note {{cannot access imaginary component of null}} + constexpr float pr = __real *p; // expected-error {{constant expr}} expected-note {{dereferencing a null pointer}} + constexpr float pi = __imag *p; // expected-error {{constant expr}} expected-note {{dereferencing a null pointer}} constexpr const _Complex double *q = &test3 + 1; // expected-warning {{'_Complex' is a C99 extension}} constexpr double qr = __real *q; // expected-error {{constant expr}} expected-note {{cannot access real component of pointer past the end}} constexpr double qi = __imag *q; // expected-error {{constant expr}} expected-note {{cannot access imaginary component of pointer past the end}} diff --git a/clang/test/SemaCXX/constant-expression-cxx14.cpp b/clang/test/SemaCXX/constant-expression-cxx14.cpp index e93b98c185a82..1743e0e3ac4b5 100644 --- a/clang/test/SemaCXX/constant-expression-cxx14.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx14.cpp @@ -265,7 +265,7 @@ namespace const_modify { namespace null { constexpr int test(int *p) { - return *p = 123; // expected-note {{assignment to dereferenced null pointer}} + return *p = 123; // expected-note {{dereferencing a null pointer}} } static_assert(test(0), ""); // expected-error {{constant expression}} expected-note {{in call}} } @@ -1335,4 +1335,118 @@ namespace comparison_dead_variable { } // FIXME: This should fail. static_assert(f(),""); + +} +namespace GH48665 { +constexpr bool foo(int *i) { + int &j = *i; + // expected-note@-1 {{dereferencing a null pointer}} + return true; +} + +static_assert(foo(nullptr), ""); // expected-note {{in call to 'foo(nullptr)'}} +// expected-error@-1 {{static assertion expression is not an integral constant expression}} + +constexpr bool foo_rvalue(int *i) { + int &&j = (int&&)*i; + // expected-note@-1 {{dereferencing a null pointer}} + return true; +} +static_assert(foo_rvalue(nullptr), ""); // expected-note {{in call to 'foo_rvalue(nullptr)'}} +// expected-error@-1 {{static assertion expression is not an integral constant expression}} + +int arr[3]; // expected-note {{declared here}} +constexpr bool f() { // cxx14_20-error {{constexpr function never produces a constant expression}} + int &r = arr[3]; // expected-note {{read of dereferenced one-past-the-end pointer}} \ + // cxx14_20-note {{read of dereferenced one-past-the-end pointer}} \ + // expected-warning {{array index 3 is past the end of the array}} + return true; +} +static_assert(f(), ""); // expected-note {{in call to 'f()'}} +// expected-error@-1 {{static assertion expression is not an integral constant expression}} + + +struct Aggregate { + int &r; +}; +constexpr bool test_agg(int *i) { + Aggregate a{*i}; //expected-note {{dereferencing a null pointer}} + return true; +} +static_assert(test_agg(nullptr), ""); // expected-note {{in call to 'test_agg(nullptr)'}} +// expected-error@-1 {{static assertion expression is not an integral constant expression}} + +struct B { + constexpr B(int *p) : r{*p} {} // expected-note {{dereferencing a null pointer}} + int &r; +}; + +constexpr bool test_ctr(int *i) { + B b(i); // expected-note {{in call to 'B(nullptr)'}} + return true; +} + +static_assert(test_ctr(nullptr), ""); // expected-note {{in call to 'test_ctr(nullptr)'}} +// expected-error@-1 {{static assertion expression is not an integral constant expression}} + + +// verify that we can dereference function pointers +namespace functions { + +constexpr int f() {return 0;} +constexpr int(*f_ptr)() = &f; +constexpr int(*null_ptr)() = nullptr; + +constexpr int(&f_ref)() = f; +constexpr int test = (*f_ptr)(); +constexpr int test2 = (*f_ref)(); +constexpr int test3 = (*f_ref)(); +constexpr int test4 = (*null_ptr)(); +//expected-error@-1 {{constexpr variable 'test4' must be initialized by a constant expression}} \ +//expected-note@-1 {{'(*null_ptr)' evaluates to a null function pointer}} + +constexpr int(*f_ptr_arr[1])() = {&f}; +constexpr int test_array_ok = (f_ptr_arr[0])(); +constexpr int test_array_err = (f_ptr_arr[1])(); +// expected-error@-1 {{constexpr variable 'test_array_err' must be initialized by a constant expression}} \ +// expected-note@-1 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} + +struct S { + int(*f_ptr)() = &f; + int(*f_ptr_arr[1])() = {&f}; + int(&f_ref)() = f; + int(*null_ptr)() = nullptr; +}; + +constexpr int test_member() { + S s {}; + (*s.f_ptr)(); + (*s.f_ref)(); + (s.f_ref)(); + (s.f_ptr_arr[0])(); + (s.f_ptr_arr[1])(); + // expected-note@-1 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} + return 0; +} +constexpr int test_member_null() { // cxx14_20-error {{never produces a constant expression}} + S s {}; + (*s.null_ptr)(); // expected-note {{'(*s.null_ptr)' evaluates to a null function pointer}} \ + // cxx14_20-note {{'(*s.null_ptr)' evaluates to a null function pointer}} + return 0; +} + +static_assert(test_member(), ""); +// expected-error@-1 {{static assertion expression is not an integral constant expression}} \ +// expected-note@-1 {{in call to 'test_member()'}} + +static_assert(test_member_null(), ""); +// expected-error@-1 {{static assertion expression is not an integral constant expression}} \ +// expected-note@-1 {{in call to 'test_member_null()'}} + +} +} + +namespace GH149500 { + unsigned int * p = &(*(unsigned int *)0x400); + static const void *q = &(*(const struct sysrq_key_op *)0); } diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp b/clang/test/SemaCXX/constant-expression-cxx2a.cpp index 85720606fe9de..ffb7e633c2919 100644 --- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp @@ -927,7 +927,7 @@ namespace dynamic_alloc { constexpr void use_after_free() { // expected-error {{never produces a constant expression}} int *p = new int; delete p; - *p = 1; // expected-note {{assignment to heap allocated object that has been deleted}} + *p = 1; // expected-note {{read of heap allocated object that has been deleted}} } constexpr void use_after_free_2() { // expected-error {{never produces a constant expression}} struct X { constexpr void f() {} }; diff --git a/clang/test/SemaCXX/constant-expression-p2280r4.cpp b/clang/test/SemaCXX/constant-expression-p2280r4.cpp index 03fea91169787..16f5f823d26c1 100644 --- a/clang/test/SemaCXX/constant-expression-p2280r4.cpp +++ b/clang/test/SemaCXX/constant-expression-p2280r4.cpp @@ -357,3 +357,29 @@ namespace pointer_comparisons { static_assert(!f4()); // expected-error {{static assertion expression is not an integral constant expression}} \ // expected-note {{in call to 'f4()'}} } + +namespace GH149188 { +namespace enable_if_1 { + template <__SIZE_TYPE__ N> + constexpr void foo(const char (&Str)[N]) + __attribute((enable_if(__builtin_strlen(Str), ""))) {} + + void x() { + foo("1234"); + } +} + +namespace enable_if_2 { + constexpr const char (&f())[]; + extern const char (&Str)[]; + constexpr int foo() + __attribute((enable_if(__builtin_strlen(Str), ""))) + {return __builtin_strlen(Str);} + + constexpr const char (&f())[] {return "a";} + constexpr const char (&Str)[] = f(); + void x() { + constexpr int x = foo(); + } +} +} diff --git a/clang/test/SemaCXX/constexpr-backtrace-limit.cpp b/clang/test/SemaCXX/constexpr-backtrace-limit.cpp index e867afdff5c3c..f0c1206a4b8d3 100644 --- a/clang/test/SemaCXX/constexpr-backtrace-limit.cpp +++ b/clang/test/SemaCXX/constexpr-backtrace-limit.cpp @@ -15,14 +15,14 @@ // RUN: not %clang_cc1 -std=c++11 -fsyntax-only %s -fconstexpr-backtrace-limit=2 -fconstexpr-depth=8 -fno-caret-diagnostics 2>&1 | FileCheck %s -check-prefix=TEST3 // TEST3: constant expression -// TEST3-NEXT: reinterpret_cast +// TEST3-NEXT: dereferencing a null pointer // TEST3-NEXT: in call to 'recurse(0)' // TEST3-NEXT: skipping 4 calls // TEST3-NEXT: in call to 'recurse(5)' // RUN: not %clang_cc1 -std=c++11 -fsyntax-only %s -fconstexpr-backtrace-limit=8 -fconstexpr-depth=8 -fno-caret-diagnostics 2>&1 | FileCheck %s -check-prefix=TEST4 // TEST4: constant expression -// TEST4-NEXT: reinterpret_cast +// TEST4-NEXT: dereferencing a null pointer // TEST4-NEXT: in call to 'recurse(0)' // TEST4-NEXT: in call to 'recurse(1)' // TEST4-NEXT: in call to 'recurse(2)' diff --git a/clang/test/SemaCXX/constexpr-never-constant.cpp b/clang/test/SemaCXX/constexpr-never-constant.cpp index 307810ee263dd..5756bb647ce88 100644 --- a/clang/test/SemaCXX/constexpr-never-constant.cpp +++ b/clang/test/SemaCXX/constexpr-never-constant.cpp @@ -24,3 +24,10 @@ constexpr void other_func() { throw 12; } + +namespace GH149041 { + // Make sure these don't trigger the diagnostic. + extern const bool& b; + constexpr bool fun1() { return b; } + constexpr bool fun2(const bool& b) { return b; } +} diff --git a/clang/test/SemaCXX/cxx2c-constexpr-placement-new.cpp b/clang/test/SemaCXX/cxx2c-constexpr-placement-new.cpp index 6f6f9b04aa392..4cf0e9ffe1d64 100644 --- a/clang/test/SemaCXX/cxx2c-constexpr-placement-new.cpp +++ b/clang/test/SemaCXX/cxx2c-constexpr-placement-new.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c++2c -verify %s +// RUN: %clang_cc1 -std=c++2c -verify %s -fexperimental-new-constant-interpreter namespace std { diff --git a/clang/test/SemaCXX/cxx2c-trivially-relocatable.cpp b/clang/test/SemaCXX/cxx2c-trivially-relocatable.cpp index 6f4003f525930..c6919447798da 100644 --- a/clang/test/SemaCXX/cxx2c-trivially-relocatable.cpp +++ b/clang/test/SemaCXX/cxx2c-trivially-relocatable.cpp @@ -372,7 +372,7 @@ void test__builtin_trivially_relocate() { __builtin_trivially_relocate((S*)0, 0, 0); //expected-error {{argument to '__builtin_trivially_relocate' must be relocatable}} __builtin_trivially_relocate((int*)0, 0, 0); //expected-error {{first and second arguments to '__builtin_trivially_relocate' must be of the same type}} - __builtin_trivially_relocate((int*)0, (int*)0, (int*)0); // expected-error-re {{cannot initialize a value of type '{{.*}}' with an rvalue of type 'int *'}} + __builtin_trivially_relocate((int*)0, (int*)0, (int*)0); // expected-error-re {{cannot initialize a value of type '__size_t' (aka '{{.*}}') with an rvalue of type 'int *'}} __builtin_trivially_relocate((int*)0, (int*)0, 0); __builtin_trivially_relocate((R*)0, (R*)0, 0); } diff --git a/clang/test/SemaCXX/diagnose_if-ext.cpp b/clang/test/SemaCXX/diagnose_if-ext.cpp index d5625b501322e..e0f73976eea3a 100644 --- a/clang/test/SemaCXX/diagnose_if-ext.cpp +++ b/clang/test/SemaCXX/diagnose_if-ext.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -Wpedantic -fsyntax-only %s -verify +// RUN: %clang_cc1 -Wpedantic -fsyntax-only %s -verify -fexperimental-new-constant-interpreter void foo() __attribute__((diagnose_if(1, "", "error"))); // expected-warning{{'diagnose_if' is a clang extension}} void foo(int a) __attribute__((diagnose_if(a, "", "error"))); // expected-warning{{'diagnose_if' is a clang extension}} diff --git a/clang/test/SemaCXX/diagnose_if.cpp b/clang/test/SemaCXX/diagnose_if.cpp index 21897c5184b73..1b9e660c4e224 100644 --- a/clang/test/SemaCXX/diagnose_if.cpp +++ b/clang/test/SemaCXX/diagnose_if.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -verify -fno-builtin -std=c++14 +// RUN: %clang_cc1 %s -verify -fno-builtin -std=c++14 -fexperimental-new-constant-interpreter #define _diagnose_if(...) __attribute__((diagnose_if(__VA_ARGS__))) diff --git a/clang/test/SemaCXX/enum-scoped.cpp b/clang/test/SemaCXX/enum-scoped.cpp index 0ce47274979d9..2d7b3c9557ebd 100644 --- a/clang/test/SemaCXX/enum-scoped.cpp +++ b/clang/test/SemaCXX/enum-scoped.cpp @@ -35,7 +35,7 @@ int a1[Val2]; int a2[E1::Val1]; #if __cplusplus >= 201703L -// expected-error@-3 {{type 'E1' is not implicitly convertible to 'unsigned long'}} +// expected-error@-3 {{type 'E1' is not implicitly convertible to '__size_t' (aka 'unsigned long')}} #else // expected-error@-5 {{size of array has non-integer type}} #endif @@ -44,7 +44,7 @@ int* p1 = new int[Val2]; int* p2 = new int[E1::Val1]; #if __cplusplus >= 201703L -// expected-error@-3 {{converting 'E1' to incompatible type 'unsigned long'}} +// expected-error@-3 {{converting 'E1' to incompatible type '__size_t'}} #else // expected-error@-5 {{array size expression must have integral or unscoped enumeration type, not 'E1'}} #endif diff --git a/clang/test/SemaCXX/microsoft-varargs-diagnostics.cpp b/clang/test/SemaCXX/microsoft-varargs-diagnostics.cpp index 0b76fdd92dabd..91c4ffda9d818 100644 --- a/clang/test/SemaCXX/microsoft-varargs-diagnostics.cpp +++ b/clang/test/SemaCXX/microsoft-varargs-diagnostics.cpp @@ -22,7 +22,7 @@ void test_non_last_argument(int i, int j, ...) { va_list ap; __va_start(&ap, &i, 4); // expected-error@-1{{passing 'int *' to parameter of incompatible type 'const char *': type mismatch at 2nd parameter ('int *' vs 'const char *')}} - // expected-error@-2{{passing 'int' to parameter of incompatible type 'unsigned int': type mismatch at 3rd parameter ('int' vs 'unsigned int')}} + // expected-error@-2{{passing 'int' to parameter of incompatible type '__size_t' (aka 'unsigned int'): type mismatch at 3rd parameter ('int' vs '__size_t' (aka 'unsigned int'))}} } void test_stack_allocated(int i, ...) { @@ -30,13 +30,13 @@ void test_stack_allocated(int i, ...) { int j; __va_start(&ap, &j, 4); // expected-error@-1{{passing 'int *' to parameter of incompatible type 'const char *': type mismatch at 2nd parameter ('int *' vs 'const char *')}} - // expected-error@-2{{passing 'int' to parameter of incompatible type 'unsigned int': type mismatch at 3rd parameter ('int' vs 'unsigned int')}} + // expected-error@-2{{passing 'int' to parameter of incompatible type '__size_t' (aka 'unsigned int'): type mismatch at 3rd parameter ('int' vs '__size_t' (aka 'unsigned int'))}} } void test_non_pointer_addressof(int i, ...) { va_list ap; __va_start(&ap, 1, 4); // expected-error@-1{{passing 'int' to parameter of incompatible type 'const char *': type mismatch at 2nd parameter ('int' vs 'const char *')}} - // expected-error@-2{{passing 'int' to parameter of incompatible type 'unsigned int': type mismatch at 3rd parameter ('int' vs 'unsigned int')}} + // expected-error@-2{{passing 'int' to parameter of incompatible type '__size_t' (aka 'unsigned int'): type mismatch at 3rd parameter ('int' vs '__size_t' (aka 'unsigned int'))}} } diff --git a/clang/test/SemaCXX/new-delete.cpp b/clang/test/SemaCXX/new-delete.cpp index f918501554f80..c05130bb30729 100644 --- a/clang/test/SemaCXX/new-delete.cpp +++ b/clang/test/SemaCXX/new-delete.cpp @@ -109,7 +109,7 @@ void bad_news(int *ip) #elif __cplusplus <= 201103L // expected-error@-4 {{array size expression must have integral or unscoped enumeration type, not 'double'}} #else - // expected-warning@-6 {{implicit conversion from 'double' to 'unsigned int' changes value from 1.1 to 1}} + // expected-warning@-6 {{implicit conversion from 'double' to '__size_t' (aka 'unsigned int') changes value from 1.1 to 1}} #endif (void)new int[1][i]; // expected-note {{read of non-const variable 'i' is not allowed in a constant expression}} diff --git a/clang/test/SemaCXX/static-assert-cxx26.cpp b/clang/test/SemaCXX/static-assert-cxx26.cpp index b53c67ee67932..b2ebd2abb785e 100644 --- a/clang/test/SemaCXX/static-assert-cxx26.cpp +++ b/clang/test/SemaCXX/static-assert-cxx26.cpp @@ -19,7 +19,7 @@ struct InvalidSize { const char* data() const; }; static_assert(true, InvalidSize{}); // expected-error {{the message in a static assertion must have a 'size()' member function returning an object convertible to 'std::size_t'}} \ - // expected-error {{value of type 'const char *' is not implicitly convertible to 'unsigned long'}} + // expected-error {{value of type 'const char *' is not implicitly convertible to '__size_t' (aka 'unsigned long')}} struct InvalidData { unsigned long size() const; unsigned long data() const; @@ -371,13 +371,13 @@ struct E { static_assert(true, A{}); // expected-error {{the message in this static assertion is not a constant expression}} // expected-note@-1 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} -static_assert(true, B{}); // expected-error {{call to 'size()' evaluates to -1, which cannot be narrowed to type 'unsigned long'}} +static_assert(true, B{}); // expected-error {{call to 'size()' evaluates to -1, which cannot be narrowed to type '__size_t' (aka 'unsigned long')}} // expected-error@-1 {{the message in this static assertion is not a constant expression}} // expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} -static_assert(true, C{}); // expected-error {{call to 'size()' evaluates to -1, which cannot be narrowed to type 'unsigned long'}} +static_assert(true, C{}); // expected-error {{call to 'size()' evaluates to -1, which cannot be narrowed to type '__size_t' (aka 'unsigned long')}} // expected-error@-1 {{the message in this static assertion is not a constant expression}} // expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} -static_assert(true, D{}); // expected-error {{call to 'size()' evaluates to 340282366920938463463374607431768211455, which cannot be narrowed to type 'unsigned long'}} +static_assert(true, D{}); // expected-error {{call to 'size()' evaluates to 340282366920938463463374607431768211455, which cannot be narrowed to type '__size_t' (aka 'unsigned long')}} // expected-error@-1 {{the message in this static assertion is not a constant expression}} // expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} static_assert(true, E{}); // expected-error {{the message in this static assertion is not a constant expression}} @@ -391,21 +391,21 @@ static_assert( static_assert( false, // expected-error {{static assertion failed}} - B{} // expected-error {{call to 'size()' evaluates to -1, which cannot be narrowed to type 'unsigned long'}} + B{} // expected-error {{call to 'size()' evaluates to -1, which cannot be narrowed to type '__size_t' (aka 'unsigned long')}} // expected-error@-1 {{the message in a static assertion must be produced by a constant expression}} // expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} ); static_assert( false, // expected-error {{static assertion failed}} - C{} // expected-error {{call to 'size()' evaluates to -1, which cannot be narrowed to type 'unsigned long'}} + C{} // expected-error {{call to 'size()' evaluates to -1, which cannot be narrowed to type '__size_t' (aka 'unsigned long')}} // expected-error@-1 {{the message in a static assertion must be produced by a constant expression}} // expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} ); static_assert( false, // expected-error {{static assertion failed}} - D{} // expected-error {{call to 'size()' evaluates to 340282366920938463463374607431768211455, which cannot be narrowed to type 'unsigned long'}} + D{} // expected-error {{call to 'size()' evaluates to 340282366920938463463374607431768211455, which cannot be narrowed to type '__size_t' (aka 'unsigned long')}} // expected-error@-1 {{the message in a static assertion must be produced by a constant expression}} // expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} ); diff --git a/clang/test/SemaCXX/type-aware-new-delete-basic-free-declarations.cpp b/clang/test/SemaCXX/type-aware-new-delete-basic-free-declarations.cpp index 87dc58861ee81..281ef5fa63d6f 100644 --- a/clang/test/SemaCXX/type-aware-new-delete-basic-free-declarations.cpp +++ b/clang/test/SemaCXX/type-aware-new-delete-basic-free-declarations.cpp @@ -75,7 +75,7 @@ template void *operator new(std::type_identity, U); template void operator delete(std::type_identity, U, size_t, std::align_val_t); // expected-error@-1 {{type aware 'operator delete' cannot take a dependent type as its 2nd parameter; use 'void *' instead}} template void operator delete(std::type_identity, void *, U, std::align_val_t); -// expected-error@-1 {{type aware 'operator delete' cannot take a dependent type as its 3rd parameter; use 'unsigned long' instead}} +// expected-error@-1 {{type aware 'operator delete' cannot take a dependent type as its 3rd parameter; use '__size_t' (aka 'unsigned long') instead}} template void operator delete(std::type_identity, void *, size_t, U); // expected-error@-1 {{type aware 'operator delete' cannot take a dependent type as its 4th parameter; use 'std::align_val_t' instead}} template void *operator new(std::type_identity, typename S::size_ty, std::align_val_t); diff --git a/clang/test/SemaCXX/unavailable_aligned_allocation.cpp b/clang/test/SemaCXX/unavailable_aligned_allocation.cpp index 45fdec606ad1b..56c564f170271 100644 --- a/clang/test/SemaCXX/unavailable_aligned_allocation.cpp +++ b/clang/test/SemaCXX/unavailable_aligned_allocation.cpp @@ -65,12 +65,12 @@ void testOveraligned() { #ifdef NO_ERRORS // expected-no-diagnostics #else -// expected-error-re@-16 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is {{only|not}} available on}} +// expected-error-re@-16 {{aligned allocation function of type 'void *(__size_t, enum std::align_val_t)' is {{only|not}} available on}} // expected-note@-17 {{if you supply your own aligned allocation functions}} // expected-error-re@-18 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is {{only|not}} available on}} // expected-note@-19 {{if you supply your own aligned allocation functions}} -// expected-error-re@-20 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is {{only|not}} available on}} +// expected-error-re@-20 {{aligned allocation function of type 'void *(__size_t, enum std::align_val_t)' is {{only|not}} available on}} // expected-note@-21 {{if you supply your own aligned allocation functions}} // expected-error-re@-22 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is {{only|not}} available on}} // expected-note@-23 {{if you supply your own aligned allocation functions}} @@ -83,12 +83,12 @@ void testOveraligned() { // expected-error-re@-28 {{aligned deallocation function of type 'void (void *, std::align_val_t, const std::nothrow_t &) noexcept' is {{only|not}} available on}} // expected-note@-29 {{if you supply your own aligned allocation functions}} -// expected-error-re@-29 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is {{only|not}} available on}} +// expected-error-re@-29 {{aligned allocation function of type 'void *(__size_t, enum std::align_val_t)' is {{only|not}} available on}} // expected-note@-30 {{if you supply your own aligned allocation functions}} // expected-error-re@-31 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is {{only|not}} available on}} // expected-note@-32 {{if you supply your own aligned allocation functions}} -// expected-error-re@-33 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is {{only|not}} available on}} +// expected-error-re@-33 {{aligned allocation function of type 'void *(__size_t, enum std::align_val_t)' is {{only|not}} available on}} // expected-note@-34 {{if you supply your own aligned allocation functions}} // expected-error-re@-35 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is {{only|not}} available on}} // expected-note@-36 {{if you supply your own aligned allocation functions}} @@ -111,19 +111,19 @@ void testOveralignedCheckOS() { // expected-no-diagnostics #else #if defined(IOS) -// expected-error@-7 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is only available on iOS 11 or newer}} +// expected-error@-7 {{aligned allocation function of type 'void *(__size_t, enum std::align_val_t)' is only available on iOS 11 or newer}} // expected-error@-8 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on iOS 11 or newer}}} #elif defined(TVOS) -// expected-error@-10 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is only available on tvOS 11 or newer}}} +// expected-error@-10 {{aligned allocation function of type 'void *(__size_t, enum std::align_val_t)' is only available on tvOS 11 or newer}}} // expected-error@-11 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on tvOS 11 or newer}}} #elif defined(WATCHOS) -// expected-error@-13 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is only available on watchOS 4 or newer}}} +// expected-error@-13 {{aligned allocation function of type 'void *(__size_t, enum std::align_val_t)' is only available on watchOS 4 or newer}}} // expected-error@-14 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on watchOS 4 or newer}}} #elif defined(MACOS) -// expected-error@-16 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is only available on macOS 10.13 or newer}}} +// expected-error@-16 {{aligned allocation function of type 'void *(__size_t, enum std::align_val_t)' is only available on macOS 10.13 or newer}}} // expected-error@-17 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on macOS 10.13 or newer}}} #elif defined(ZOS) -// expected-error@-19 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is not available on z/OS}}} +// expected-error@-19 {{aligned allocation function of type 'void *(__size_t, enum std::align_val_t)' is not available on z/OS}}} // expected-error@-20 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is not available on z/OS}}} #endif @@ -181,19 +181,19 @@ void testExplicitOperatorNewDeleteOveraligned() { #ifdef NO_ERRORS // expected-no-diagnostics #else -// expected-error-re@-11 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is {{only|not}} available on}} +// expected-error-re@-11 {{aligned allocation function of type 'void *(__size_t, enum std::align_val_t)' is {{only|not}} available on}} // expected-note@-12 {{if you supply your own aligned allocation functions}} // expected-error-re@-13 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is {{only|not}} available on}} // expected-note@-14 {{if you supply your own aligned allocation functions}} -// expected-error-re@-15 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is {{only|not}} available on}} +// expected-error-re@-15 {{aligned allocation function of type 'void *(__size_t, enum std::align_val_t)' is {{only|not}} available on}} // expected-note@-16 {{if you supply your own aligned allocation functions}} // expected-error-re@-17 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is {{only|not}} available on}} // expected-note@-18 {{if you supply your own aligned allocation functions}} -// expected-error-re@-19 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is {{only|not}} available on}} +// expected-error-re@-19 {{aligned allocation function of type 'void *(__size_t, enum std::align_val_t)' is {{only|not}} available on}} // expected-note@-20 {{if you supply your own aligned allocation functions}} // expected-error-re@-21 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is {{only|not}} available on}} diff --git a/clang/test/SemaHLSL/BuiltIns/refract-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/refract-errors.hlsl new file mode 100644 index 0000000000000..6cb3e56c20f0e --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/refract-errors.hlsl @@ -0,0 +1,66 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify + +float test_no_second_arg(float3 p0) { + return refract(p0); + // expected-error@-1 {{no matching function for call to 'refract'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 1 was provided}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 1 was provided}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 1 was provided}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 1 was provided}} +} + +float test_no_third_arg(float3 p0) { + return refract(p0, p0); + // expected-error@-1 {{no matching function for call to 'refract'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 2 were provided}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 2 were provided}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 2 were provided}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 2 were provided}} +} + +float test_too_many_arg(float2 p0) { + return refract(p0, p0, p0, p0); + // expected-error@-1 {{no matching function for call to 'refract'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 4 were provided}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 4 were provided}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 4 were provided}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 4 were provided}} +} + +float test_double_inputs(double p0, double p1, double p2) { + return refract(p0, p1, p2); + // expected-error@-1 {{no matching function for call to 'refract'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} +} + +float test_int_inputs(int p0, int p1, int p2) { + return refract(p0, p1, p2); + // expected-error@-1 {{no matching function for call to 'refract'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} +} + +float1 test_vec1_inputs(float1 p0, float1 p1, float1 p2) { + return refract(p0, p1, p2); + // expected-error@-1 {{no matching function for call to 'refract'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = float1]: no type named 'Type' in 'hlsl::__detail::enable_if>'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = float1]: no type named 'Type' in 'hlsl::__detail::enable_if>'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with L = 1]: no type named 'Type' in 'hlsl::__detail::enable_if'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with L = 1]: no type named 'Type' in 'hlsl::__detail::enable_if'}} +} + +typedef float float5 __attribute__((ext_vector_type(5))); + +float5 test_vec5_inputs(float5 p0, float5 p1, float p2) { + return refract(p0, p1, p2); + // expected-error@-1 {{no matching function for call to 'refract'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: deduced conflicting types for parameter 'T' ('float5' (vector of 5 'float' values) vs. 'float')}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: deduced conflicting types for parameter 'T' ('float5' (vector of 5 'float' values) vs. 'float')}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with L = 5]: no type named 'Type' in 'hlsl::__detail::enable_if'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with L = 5]: no type named 'Type' in 'hlsl::__detail::enable_if'}} +} diff --git a/clang/test/SemaHLSL/Language/AssignArray.hlsl b/clang/test/SemaHLSL/Language/AssignArray.hlsl index 1f813e7a350b1..16b60fe40f806 100644 --- a/clang/test/SemaHLSL/Language/AssignArray.hlsl +++ b/clang/test/SemaHLSL/Language/AssignArray.hlsl @@ -13,7 +13,7 @@ export void fn(int8 A) { // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector *' // CHECK-NEXT: OpaqueValueExpr {{.*}} 'int8':'vector[2]' lvalue // CHECK-NEXT: DeclRefExpr {{.*}} 'int8':'vector[2]' lvalue Var {{.*}} 'a' 'int8':'vector[2]' -// CHECK-NEXT: ArrayInitIndexExpr {{.*}} 'unsigned long' +// CHECK-NEXT: ArrayInitIndexExpr {{.*}} '__size_t':'unsigned long' int8 b = a; // CHECK-LABEL: VarDecl {{.*}} c 'int8':'vector[2]' cinit @@ -25,7 +25,7 @@ export void fn(int8 A) { // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector *' // CHECK-NEXT: OpaqueValueExpr {{.*}} 'vector[2]' lvalue // CHECK-NEXT: DeclRefExpr {{.*}} 'vector[2]' lvalue ParmVar {{.*}} 'A' 'vector[2]' -// CHECK-NEXT: ArrayInitIndexExpr {{.*}} 'unsigned long' +// CHECK-NEXT: ArrayInitIndexExpr {{.*}} '__size_t':'unsigned long' int8 c = A; } diff --git a/clang/test/SemaHLSL/Language/InitListAST.hlsl b/clang/test/SemaHLSL/Language/InitListAST.hlsl index 78bf269769ae6..460ec38bb44af 100644 --- a/clang/test/SemaHLSL/Language/InitListAST.hlsl +++ b/clang/test/SemaHLSL/Language/InitListAST.hlsl @@ -97,12 +97,12 @@ TwoFloats case3(int Val) { // CHECK-NEXT: ImplicitCastExpr {{.*}}'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent // CHECK-NEXT: DeclRefExpr {{.*}} 'int2':'vector' lvalue ParmVar {{.*}} 'TwoVals' 'int2':'vector' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent // CHECK-NEXT: DeclRefExpr {{.*}} 'int2':'vector' lvalue ParmVar {{.*}} 'TwoVals' 'int2':'vector' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 TwoFloats case4(int2 TwoVals) { TwoFloats TF4 = {TwoVals}; return TF4; @@ -115,11 +115,11 @@ TwoFloats case4(int2 TwoVals) { // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent // CHECK-NEXT: DeclRefExpr {{.*}} 'int2':'vector' lvalue ParmVar {{.*}} 'TwoVals' 'int2':'vector' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent // CHECK-NEXT: DeclRefExpr {{.*}} 'int2':'vector' lvalue ParmVar {{.*}} 'TwoVals' 'int2':'vector' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 TwoInts case5(int2 TwoVals) { TwoInts TI1 = {TwoVals}; return TI1; @@ -209,22 +209,22 @@ Doggo case7(TwoInts TI1, TwoInts TI2, int Val, TwoFloats TF1, TwoFloats TF2, // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector' lvalue .LegState {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector' lvalue .LegState {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector' lvalue .LegState {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector' lvalue .LegState {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .TailState {{.*}} @@ -240,32 +240,32 @@ Doggo case7(TwoInts TI1, TwoInts TI2, int Val, TwoFloats TF1, TwoFloats TF2, // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 // CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent @@ -273,32 +273,32 @@ Doggo case7(TwoInts TI1, TwoInts TI2, int Val, TwoFloats TF1, TwoFloats TF2, // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 AnimalBits case8(Doggo D1) { AnimalBits A1 = {D1}; return A1; @@ -317,22 +317,22 @@ AnimalBits case8(Doggo D1) { // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector' lvalue .LegState {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector' lvalue .LegState {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector' lvalue .LegState {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector' lvalue .LegState {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .TailState {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' @@ -347,32 +347,32 @@ AnimalBits case8(Doggo D1) { // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 // CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent @@ -380,32 +380,32 @@ AnimalBits case8(Doggo D1) { // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 // CHECK-NEXT: InitListExpr {{.*}} 'Doggo' // CHECK-NEXT: InitListExpr {{.*}} 'int4':'vector' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' @@ -413,25 +413,25 @@ AnimalBits case8(Doggo D1) { // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' // CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' // CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' // CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' // CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'uint':'unsigned int' // CHECK-NEXT: MemberExpr {{.*}} 'uint':'unsigned int' lvalue .State {{.*}} @@ -446,43 +446,43 @@ AnimalBits case8(Doggo D1) { // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .LeftDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .LeftDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .LeftDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .LeftDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 // CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .RightDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .RightDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .RightDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .RightDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 // CHECK-NEXT: InitListExpr {{.*}} 'Kitteh[4]' // CHECK-NEXT: InitListExpr {{.*}} 'Kitteh' // CHECK-NEXT: InitListExpr {{.*}} 'int4':'vector' @@ -490,22 +490,22 @@ AnimalBits case8(Doggo D1) { // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector' lvalue .LegState {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector' lvalue .LegState {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector' lvalue .LegState {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector' lvalue .LegState {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .TailState {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' @@ -520,32 +520,32 @@ AnimalBits case8(Doggo D1) { // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 // CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent @@ -553,32 +553,32 @@ AnimalBits case8(Doggo D1) { // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 // CHECK-NEXT: InitListExpr {{.*}} 'Kitteh' // CHECK-NEXT: InitListExpr {{.*}} 'int4':'vector' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' @@ -586,25 +586,25 @@ AnimalBits case8(Doggo D1) { // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' // CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' // CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' // CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' // CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'uint':'unsigned int' // CHECK-NEXT: MemberExpr {{.*}} 'uint':'unsigned int' lvalue .State {{.*}} @@ -619,65 +619,65 @@ AnimalBits case8(Doggo D1) { // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .LeftDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .LeftDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .LeftDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .LeftDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 // CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .RightDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .RightDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .RightDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .RightDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 // CHECK-NEXT: InitListExpr {{.*}} 'Kitteh' // CHECK-NEXT: InitListExpr {{.*}} 'int4':'vector' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector' lvalue .LegState {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector' lvalue .LegState {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector' lvalue .LegState {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector' lvalue .LegState {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .TailState {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' @@ -692,32 +692,32 @@ AnimalBits case8(Doggo D1) { // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 // CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent @@ -725,32 +725,32 @@ AnimalBits case8(Doggo D1) { // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' // CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 // CHECK-NEXT: InitListExpr {{.*}} 'Kitteh' // CHECK-NEXT: InitListExpr {{.*}} 'int4':'vector' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' @@ -758,25 +758,25 @@ AnimalBits case8(Doggo D1) { // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' // CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' // CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' // CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' // CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'uint':'unsigned int' // CHECK-NEXT: MemberExpr {{.*}} 'uint':'unsigned int' lvalue .State {{.*}} @@ -791,43 +791,43 @@ AnimalBits case8(Doggo D1) { // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .LeftDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .LeftDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .LeftDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .LeftDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 // CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .RightDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .RightDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .RightDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent // CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector' lvalue .RightDir {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 Zoo case9(Doggo D1, AnimalBits A1) { Zoo Z1 = {D1, A1, D1, A1, D1, A1}; return Z1; @@ -867,28 +867,28 @@ FourFloats case10(TwoFloats TF1, TwoFloats TF2) { // CHECK-NEXT: ExtVectorElementExpr {{.*}} 'vector' xxxx // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector' lvalue // CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'F' 'float' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' xvalue vectorcomponent // CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'vector' xvalue // CHECK-NEXT: ExtVectorElementExpr {{.*}} 'vector' xxxx // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector' lvalue // CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'F' 'float' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' xvalue vectorcomponent // CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'vector' xvalue // CHECK-NEXT: ExtVectorElementExpr {{.*}} 'vector' xxxx // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector' lvalue // CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'F' 'float' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 2 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' xvalue vectorcomponent // CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'vector' xvalue // CHECK-NEXT: ExtVectorElementExpr {{.*}} 'vector' xxxx // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector' lvalue // CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'F' 'float' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 3 FourFloats case11(float F) { FourFloats FF1 = {F.xxxx}; return FF1; @@ -1008,52 +1008,52 @@ FourFloats case16() { // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'IntAndFloat' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'IntAndFloat *' // CHECK-NEXT: DeclRefExpr {{.*}} 'IntAndFloat[2]' lvalue Var {{.*}} 'Structs' 'IntAndFloat[2]' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .B {{.*}} // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'IntAndFloat' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'IntAndFloat *' // CHECK-NEXT: DeclRefExpr {{.*}} 'IntAndFloat[2]' lvalue Var {{.*}} 'Structs' 'IntAndFloat[2]' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .A {{.*}} // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'IntAndFloat' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'IntAndFloat *' // CHECK-NEXT: DeclRefExpr {{.*}} 'IntAndFloat[2]' lvalue Var {{.*}} 'Structs' 'IntAndFloat[2]' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .B {{.*}} // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'IntAndFloat' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'IntAndFloat *' // CHECK-NEXT: DeclRefExpr {{.*}} 'IntAndFloat[2]' lvalue Var {{.*}} 'Structs' 'IntAndFloat[2]' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .A {{.*}} // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'IntAndFloat' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'IntAndFloat *' // CHECK-NEXT: DeclRefExpr {{.*}} 'IntAndFloat[2]' lvalue Var {{.*}} 'Structs' 'IntAndFloat[2]' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .B {{.*}} // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'IntAndFloat' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'IntAndFloat *' // CHECK-NEXT: DeclRefExpr {{.*}} 'IntAndFloat[2]' lvalue Var {{.*}} 'Structs' 'IntAndFloat[2]' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .A {{.*}} // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'IntAndFloat' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'IntAndFloat *' // CHECK-NEXT: DeclRefExpr {{.*}} 'IntAndFloat[2]' lvalue Var {{.*}} 'Structs' 'IntAndFloat[2]' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .B {{.*}} // CHECK-NEXT: ArraySubscriptExpr {{.*}} 'IntAndFloat' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'IntAndFloat *' // CHECK-NEXT: DeclRefExpr {{.*}} 'IntAndFloat[2]' lvalue Var {{.*}} 'Structs' 'IntAndFloat[2]' -// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1 float case17() { IntAndFloat Structs[] = {1,2,3,4}; float Floats[] = {Structs, Structs}; diff --git a/clang/test/SemaObjC/matrix-type-builtins.m b/clang/test/SemaObjC/matrix-type-builtins.m index 21b8bf864271d..3916017cf0fe0 100644 --- a/clang/test/SemaObjC/matrix-type-builtins.m +++ b/clang/test/SemaObjC/matrix-type-builtins.m @@ -27,5 +27,5 @@ void test_element_type_mismatch(u4x4 m, MatrixValue *mv) { __builtin_matrix_column_major_store(mv.value, mv.value, mv.value); // expected-error@-1 {{2nd argument must be a pointer to a valid matrix element type}} - // expected-error@-2 {{casting 'double4x4' (aka 'double __attribute__((matrix_type(4, 4)))') to incompatible type 'unsigned long}} + // expected-error@-2 {{casting 'double4x4' (aka 'double __attribute__((matrix_type(4, 4)))') to incompatible type '__size_t' (aka 'unsigned long')}} } diff --git a/clang/test/SemaOpenACC/private_firstprivate_reduction_required_ops.cpp b/clang/test/SemaOpenACC/private_firstprivate_reduction_required_ops.cpp new file mode 100644 index 0000000000000..e0aee123fe754 --- /dev/null +++ b/clang/test/SemaOpenACC/private_firstprivate_reduction_required_ops.cpp @@ -0,0 +1,103 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +struct ImplicitCtorDtor{}; + +struct ImplDeletedCtor{ + ImplDeletedCtor(int i); +}; + +struct DefaultedCtor { + DefaultedCtor() = default; +}; + +struct ImpledCtor { + ImpledCtor() = default; +}; + + +struct DeletedCtor { + DeletedCtor() = delete; +}; + +struct ImpledDtor { + ~ImpledDtor(); +}; + +struct DefaultedDtor { + ~DefaultedDtor() = default; +}; + +struct DeletedDtor { + ~DeletedDtor() = delete; +}; + +struct ImplicitDelDtor { + DeletedDtor d; +}; + +void private_uses(ImplicitCtorDtor &CDT, ImplDeletedCtor &IDC, + DefaultedCtor &DefC, ImpledCtor &IC, DeletedCtor &DelC, + ImpledDtor &ID, DefaultedDtor &DefD, DeletedDtor &DelD, + ImplicitDelDtor &IDD) { + +#pragma acc parallel private(CDT) + ; + + // expected-error@+1{{variable of type 'ImplDeletedCtor' referenced in OpenACC 'private' clause does not have a default constructor; reference has no effect}} +#pragma acc parallel private(IDC) + ; + +#pragma acc parallel private(DefC) + ; + +#pragma acc parallel private(IC) + ; + + // expected-error@+1{{variable of type 'DeletedCtor' referenced in OpenACC 'private' clause does not have a default constructor; reference has no effect}} +#pragma acc parallel private(DelC) + ; + +#pragma acc parallel private(ID) + ; + +#pragma acc parallel private(DefD) + ; + + // expected-error@+1{{variable of type 'DeletedDtor' referenced in OpenACC 'private' clause does not have a destructor; reference has no effect}} +#pragma acc parallel private(DelD) + ; + + // expected-error@+1{{variable of type 'ImplicitDelDtor' referenced in OpenACC 'private' clause does not have a destructor; reference has no effect}} +#pragma acc parallel private(IDD) + ; + +} + +template +void private_templ(T& t) { +#pragma acc parallel private(t) // #PRIV + ; +} + +void inst(ImplicitCtorDtor &CDT, ImplDeletedCtor &IDC, + DefaultedCtor &DefC, ImpledCtor &IC, DeletedCtor &DelC, + ImpledDtor &ID, DefaultedDtor &DefD, DeletedDtor &DelD, + ImplicitDelDtor &IDD) { + private_templ(CDT); + // expected-error@#PRIV{{variable of type 'ImplDeletedCtor' referenced in OpenACC 'private' clause does not have a default constructor; reference has no effect}} + // expected-note@+1{{in instantiation}} + private_templ(IDC); + private_templ(DefC); + private_templ(IC); + // expected-error@#PRIV{{variable of type 'DeletedCtor' referenced in OpenACC 'private' clause does not have a default constructor; reference has no effect}} + // expected-note@+1{{in instantiation}} + private_templ(DelC); + private_templ(ID); + private_templ(DefD); + // expected-error@#PRIV{{variable of type 'DeletedDtor' referenced in OpenACC 'private' clause does not have a destructor; reference has no effect}} + // expected-note@+1{{in instantiation}} + private_templ(DelD); + // expected-error@#PRIV{{variable of type 'ImplicitDelDtor' referenced in OpenACC 'private' clause does not have a destructor; reference has no effect}} + // expected-note@+1{{in instantiation}} + private_templ(IDD); +} diff --git a/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx1250-wmma-w32-param.cl b/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx1250-wmma-w32-param.cl index 55d705e6ad238..8aa7c34672783 100644 --- a/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx1250-wmma-w32-param.cl +++ b/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx1250-wmma-w32-param.cl @@ -114,6 +114,13 @@ void test_amdgcn_wmma_i32_16x16x64_iu8(global v8i* out, v8i a, v8i b, v8i c, int *out = __builtin_amdgcn_wmma_i32_16x16x64_iu8(0, a, 0, b, c, false, mod); // expected-error {{'__builtin_amdgcn_wmma_i32_16x16x64_iu8' must be a constant integer}} } +void test_amdgcn_wmma_f32_16x16x128_f8f6f4(global v8f* out, v16i a, v16i b, v8f c, int mod) +{ + *out = __builtin_amdgcn_wmma_f32_16x16x128_f8f6f4(mod, a, 2, b, 0, c); // expected-error {{'__builtin_amdgcn_wmma_f32_16x16x128_f8f6f4' must be a constant integer}} + *out = __builtin_amdgcn_wmma_f32_16x16x128_f8f6f4(1, a, mod, b, 0, c); // expected-error {{'__builtin_amdgcn_wmma_f32_16x16x128_f8f6f4' must be a constant integer}} + *out = __builtin_amdgcn_wmma_f32_16x16x128_f8f6f4(1, a, 2, b, mod, c); // expected-error {{'__builtin_amdgcn_wmma_f32_16x16x128_f8f6f4' must be a constant integer}} +} + void test_amdgcn_wmma_f32_16x16x32_f16(global v8f* out, v16h a, v16h b, v8f c, int mod) { *out = __builtin_amdgcn_wmma_f32_16x16x32_f16(mod, a, 0, b, 0, c, false, false); // expected-error {{'__builtin_amdgcn_wmma_f32_16x16x32_f16' must be a constant integer}} diff --git a/clang/test/SemaOpenCL/builtins-amdgcn-raw-ptr-buffer-load-lds-error.cl b/clang/test/SemaOpenCL/builtins-amdgcn-raw-ptr-buffer-load-lds-error.cl index 5915393ae7f56..8fbffbeea0531 100644 --- a/clang/test/SemaOpenCL/builtins-amdgcn-raw-ptr-buffer-load-lds-error.cl +++ b/clang/test/SemaOpenCL/builtins-amdgcn-raw-ptr-buffer-load-lds-error.cl @@ -8,3 +8,10 @@ void test_amdgcn_raw_ptr_buffer_load_lds(__amdgpu_buffer_rsrc_t rsrc, __local vo __builtin_amdgcn_raw_ptr_buffer_load_lds(rsrc, lds, 4, offset, soffset, 0, x); //expected-error{{argument to '__builtin_amdgcn_raw_ptr_buffer_load_lds' must be a constant integer}} __builtin_amdgcn_raw_ptr_buffer_load_lds(rsrc, lds, 3, offset, soffset, 0, 0); //expected-error{{invalid size value}} gfx950-note{{size must be 1, 2, 4, 12 or 16}} gfx90a-note{{size must be 1, 2, or 4}} } + +void test_amdgcn_struct_ptr_buffer_load_lds(__amdgpu_buffer_rsrc_t rsrc, __local void * lds, int size, int vindex, int voffset, int soffset, int x) { + __builtin_amdgcn_struct_ptr_buffer_load_lds(rsrc, lds, x, vindex, voffset, soffset, 0, 0); //expected-error{{argument to '__builtin_amdgcn_struct_ptr_buffer_load_lds' must be a constant integer}} + __builtin_amdgcn_struct_ptr_buffer_load_lds(rsrc, lds, 4, vindex, voffset, soffset, x, 0); //expected-error{{argument to '__builtin_amdgcn_struct_ptr_buffer_load_lds' must be a constant integer}} + __builtin_amdgcn_struct_ptr_buffer_load_lds(rsrc, lds, 4, vindex, voffset, soffset, 0, x); //expected-error{{argument to '__builtin_amdgcn_struct_ptr_buffer_load_lds' must be a constant integer}} + __builtin_amdgcn_struct_ptr_buffer_load_lds(rsrc, lds, 3, vindex, voffset, soffset, 0, 0); //expected-error{{invalid size value}} gfx950-note{{size must be 1, 2, 4, 12 or 16}} gfx90a-note{{size must be 1, 2, or 4}} +} diff --git a/clang/test/SemaOpenCL/builtins-amdgcn-raw-ptr-buffer-load-lds-target-error.cl b/clang/test/SemaOpenCL/builtins-amdgcn-raw-ptr-buffer-load-lds-target-error.cl index 74944f2d93c72..cb832b9aa4845 100644 --- a/clang/test/SemaOpenCL/builtins-amdgcn-raw-ptr-buffer-load-lds-target-error.cl +++ b/clang/test/SemaOpenCL/builtins-amdgcn-raw-ptr-buffer-load-lds-target-error.cl @@ -5,6 +5,7 @@ // RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1200 -S -verify -o - %s // REQUIRES: amdgpu-registered-target -void test_amdgcn_raw_ptr_buffer_load_lds(__amdgpu_buffer_rsrc_t rsrc, __local void* lds, int offset, int soffset, int x) { +void test_amdgcn_raw_ptr_buffer_load_lds(__amdgpu_buffer_rsrc_t rsrc, __local void* lds, int vindex, int offset, int soffset) { __builtin_amdgcn_raw_ptr_buffer_load_lds(rsrc, lds, 4, offset, soffset, 0, 0); //expected-error{{needs target feature vmem-to-lds-load-insts}} + __builtin_amdgcn_struct_ptr_buffer_load_lds(rsrc, lds, 4, vindex, offset, soffset, 0, 0); //expected-error{{needs target feature vmem-to-lds-load-insts}} } diff --git a/clang/test/SemaOpenCL/cl20-device-side-enqueue.cl b/clang/test/SemaOpenCL/cl20-device-side-enqueue.cl index a44d9dd86b86a..22569fa7b443c 100644 --- a/clang/test/SemaOpenCL/cl20-device-side-enqueue.cl +++ b/clang/test/SemaOpenCL/cl20-device-side-enqueue.cl @@ -87,7 +87,7 @@ kernel void enqueue_kernel_tests(void) { }, 1024, 4294967296L); #ifdef B32 -// expected-warning@-2{{implicit conversion from 'long' to 'unsigned int' changes value from 4294967296 to 0}} +// expected-warning@-2{{implicit conversion from 'long' to '__size_t' (aka 'unsigned int') changes value from 4294967296 to 0}} #endif char c; @@ -97,7 +97,7 @@ kernel void enqueue_kernel_tests(void) { }, c, 1024L); #ifdef WCONV -// expected-warning-re@-2{{implicit conversion changes signedness: 'char' to 'unsigned {{int|long}}'}} +// expected-warning-re@-2{{implicit conversion changes signedness: 'char' to '__size_t' (aka 'unsigned {{int|long}}')}} #endif #define UINT_MAX 4294967295 @@ -107,7 +107,7 @@ kernel void enqueue_kernel_tests(void) { }, sizeof(int), sizeof(int) * UINT_MAX); #ifdef B32 -// expected-warning@-2{{implicit conversion from 'long' to 'unsigned int' changes value from 17179869180 to 4294967292}} +// expected-warning@-2{{implicit conversion from 'long' to '__size_t' (aka 'unsigned int') changes value from 17179869180 to 4294967292}} #endif typedef void (^bl_A_t)(local void *); diff --git a/clang/test/SemaSPIRV/BuiltIns/refract-errors.c b/clang/test/SemaSPIRV/BuiltIns/refract-errors.c new file mode 100644 index 0000000000000..07486c2a60cbf --- /dev/null +++ b/clang/test/SemaSPIRV/BuiltIns/refract-errors.c @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 %s -triple spirv-pc-vulkan-compute -verify + +typedef float float2 __attribute__((ext_vector_type(2))); +typedef float float3 __attribute__((ext_vector_type(3))); +typedef _Float16 half; +typedef half half2 __attribute__((ext_vector_type(2))); + +float2 test_no_third_arg(float2 p0) { + return __builtin_spirv_refract(p0, p0); + // expected-error@-1 {{too few arguments to function call, expected 3, have 2}} +} + +float2 test_too_many_arg(float2 p0, float p1) { + return __builtin_spirv_refract(p0, p0, p1, p1); + // expected-error@-1 {{too many arguments to function call, expected 3, have 4}} +} + +float test_double_scalar_inputs(double p0, double p1, double p2) { + return __builtin_spirv_refract(p0, p1, p2); + // expected-error@-1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'double')}} +} + +float test_int_scalar_inputs(int p0, int p1, int p2) { + return __builtin_spirv_refract(p0, p1, p2); + // expected-error@-1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'int')}} +} + +float test_float_and_half_inputs(float2 p0, half2 p1, float p2) { + return __builtin_spirv_refract(p0, p1, p2); + // expected-error@-1 {{first two arguments to '__builtin_spirv_refract' must have the same type}} +} + +float test_float_and_half_2_inputs(float2 p0, float2 p1, half p2) { + return __builtin_spirv_refract(p0, p1, p2); + // expected-error@-1 {{all arguments to '__builtin_spirv_refract' must be of scalar or vector type with matching scalar element type: 'float2' (vector of 2 'float' values) vs 'half' (aka '_Float16')}} +} + +float2 test_mismatch_vector_size_inputs(float2 p0, float3 p1, float p2) { + return __builtin_spirv_refract(p0, p1, p2); + // expected-error@-1 {{first two arguments to '__builtin_spirv_refract' must have the same type}} +} diff --git a/clang/test/SemaTemplate/concepts-using-decl.cpp b/clang/test/SemaTemplate/concepts-using-decl.cpp index fca69dea5c88f..41f7b6d2f8faa 100644 --- a/clang/test/SemaTemplate/concepts-using-decl.cpp +++ b/clang/test/SemaTemplate/concepts-using-decl.cpp @@ -176,3 +176,24 @@ void func() { f.foo<10, 10>(); // expected-error {{no matching member function for call to 'foo'}} } } // namespace heads_without_concepts. + +namespace GH146614 { + +template +struct base { + template + void foo(A x) + requires (requires{x;}) + {} +}; + + +struct child : base { + using base::foo; + template + void foo(A x) + requires (false) + {} +}; + +} diff --git a/clang/test/SemaTemplate/type_pack_element.cpp b/clang/test/SemaTemplate/type_pack_element.cpp index 264b4dcdc044d..5ff010c7db29c 100644 --- a/clang/test/SemaTemplate/type_pack_element.cpp +++ b/clang/test/SemaTemplate/type_pack_element.cpp @@ -7,9 +7,9 @@ using test1 = __type_pack_element<0, int>; // CHECK-NEXT: |-name: '__type_pack_element' qualified // CHECK-NEXT: | `-BuiltinTemplateDecl {{.+}} __type_pack_element // CHECK-NEXT: |-TemplateArgument expr '0' -// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} 'unsigned long' +// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} '__size_t':'unsigned long' // CHECK-NEXT: | |-value: Int 0 -// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} 'unsigned long' +// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} '__size_t':'unsigned long' // CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} 'int' 0 // CHECK-NEXT: |-TemplateArgument type 'int' // CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' @@ -23,7 +23,7 @@ template struct A { // CHECK-NEXT: |-name: '__type_pack_element' qualified // CHECK-NEXT: | `-BuiltinTemplateDecl {{.+}} __type_pack_element // CHECK-NEXT: |-TemplateArgument expr 'N' -// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} 'unsigned long' +// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} '__size_t':'unsigned long' // CHECK-NEXT: | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int' // CHECK-NEXT: `-TemplateArgument type 'Ts...' // CHECK-NEXT: `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'Ts...' dependent @@ -37,9 +37,9 @@ template struct A { // CHECK-NEXT: |-name: '__type_pack_element' qualified // CHECK-NEXT: | `-BuiltinTemplateDecl {{.+}} __type_pack_element // CHECK-NEXT: |-TemplateArgument expr '0' -// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} 'unsigned long' +// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} '__size_t':'unsigned long' // CHECK-NEXT: | |-value: Int 0 -// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} 'unsigned long' +// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} '__size_t':'unsigned long' // CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} 'int' 0 // CHECK-NEXT: `-TemplateArgument type 'Ts...' // CHECK-NEXT: `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'Ts...' dependent @@ -53,7 +53,7 @@ template struct A { // CHECK-NEXT: |-name: '__type_pack_element' qualified // CHECK-NEXT: | `-BuiltinTemplateDecl {{.+}} __type_pack_element // CHECK-NEXT: |-TemplateArgument expr 'N' -// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} 'unsigned long' +// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} '__size_t':'unsigned long' // CHECK-NEXT: | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int' // CHECK-NEXT: `-TemplateArgument type 'int' // CHECK-NEXT: `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 9089984fa4a54..9412d9735ef82 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1438,10 +1438,6 @@ bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS, return Visit( MakeCursorNamespaceRef(NNS->getAsNamespace(), Range.getBegin(), TU)); - case NestedNameSpecifier::NamespaceAlias: - return Visit(MakeCursorNamespaceRef(NNS->getAsNamespaceAlias(), - Range.getBegin(), TU)); - case NestedNameSpecifier::TypeSpec: { // If the type has a form where we know that the beginning of the source // range matches up with a reference cursor. Visit the appropriate reference @@ -1483,13 +1479,6 @@ bool CursorVisitor::VisitNestedNameSpecifierLoc( break; - case NestedNameSpecifier::NamespaceAlias: - if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespaceAlias(), - Q.getLocalBeginLoc(), TU))) - return true; - - break; - case NestedNameSpecifier::TypeSpec: if (Visit(Q.getTypeLoc())) return true; @@ -1683,6 +1672,10 @@ bool CursorVisitor::VisitTypedefTypeLoc(TypedefTypeLoc TL) { return Visit(MakeCursorTypeRef(TL.getTypedefNameDecl(), TL.getNameLoc(), TU)); } +bool CursorVisitor::VisitPredefinedSugarTypeLoc(PredefinedSugarTypeLoc TL) { + return false; +} + bool CursorVisitor::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) { return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU)); } diff --git a/clang/tools/libclang/CMakeLists.txt b/clang/tools/libclang/CMakeLists.txt index b6662b66206b2..2b1e266f07392 100644 --- a/clang/tools/libclang/CMakeLists.txt +++ b/clang/tools/libclang/CMakeLists.txt @@ -42,6 +42,7 @@ set(SOURCES Indexing.cpp FatalErrorHandler.cpp Rewrite.cpp + Obsolete.cpp ADDITIONAL_HEADERS CIndexDiagnostic.h diff --git a/clang/tools/libclang/Obsolete.cpp b/clang/tools/libclang/Obsolete.cpp new file mode 100644 index 0000000000000..3596f76e1be6f --- /dev/null +++ b/clang/tools/libclang/Obsolete.cpp @@ -0,0 +1,48 @@ +//===- Obsolete.cpp - Obsolete libclang functions and types -------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--------------------------------------------------------------------===// +// +// This file contains libclang symbols whose underlying functionality has been +// removed from Clang, but which need to be kept around so as to retain ABI +// compatibility. +// +//===--------------------------------------------------------------------===// + +#include "clang-c/CXString.h" +#include "clang-c/Index.h" +#include "clang-c/Platform.h" +#include "llvm/Support/raw_ostream.h" + +extern "C" { + +// The functions below used to be part of the C API for ARCMigrate, which has +// since been removed from Clang; they already used to print an error if Clang +// was compiled without arcmt support, so we continue doing so. +CXRemapping clang_getRemappings(const char *) { + llvm::errs() << "error: ARCMigrate has been removed from Clang"; + return nullptr; +} + +CXRemapping clang_getRemappingsFromFileList(const char **, unsigned) { + llvm::errs() << "error: ARCMigrate has been removed from Clang"; + return nullptr; +} + +unsigned clang_remap_getNumFiles(CXRemapping) { + llvm::errs() << "error: ARCMigrate has been removed from Clang"; + return 0; +} + +void clang_remap_getFilenames(CXRemapping, unsigned, CXString *, CXString *) { + llvm::errs() << "error: ARCMigrate has been removed from Clang"; +} + +void clang_remap_dispose(CXRemapping) { + llvm::errs() << "error: ARCMigrate has been removed from Clang"; +} + +} // extern "C" diff --git a/clang/tools/libclang/libclang.map b/clang/tools/libclang/libclang.map index 49c472e3833fd..3d9d2e268a611 100644 --- a/clang/tools/libclang/libclang.map +++ b/clang/tools/libclang/libclang.map @@ -327,6 +327,8 @@ LLVM_13 { clang_getRange; clang_getRangeEnd; clang_getRangeStart; + clang_getRemappings; + clang_getRemappingsFromFileList; clang_getResultType; clang_getSkippedRanges; clang_getSpecializedCursorTemplate; @@ -387,6 +389,9 @@ LLVM_13 { clang_parseTranslationUnit; clang_parseTranslationUnit2; clang_parseTranslationUnit2FullArgv; + clang_remap_dispose; + clang_remap_getFilenames; + clang_remap_getNumFiles; clang_reparseTranslationUnit; clang_saveTranslationUnit; clang_sortCodeCompletionResults; diff --git a/clang/unittests/Analysis/CMakeLists.txt b/clang/unittests/Analysis/CMakeLists.txt index 059a74843155c..52e7d2854633d 100644 --- a/clang/unittests/Analysis/CMakeLists.txt +++ b/clang/unittests/Analysis/CMakeLists.txt @@ -4,6 +4,7 @@ add_clang_unittest(ClangAnalysisTests CloneDetectionTest.cpp ExprMutationAnalyzerTest.cpp IntervalPartitionTest.cpp + LifetimeSafetyTest.cpp MacroExpansionContextTest.cpp UnsafeBufferUsageTest.cpp CLANG_LIBS diff --git a/clang/unittests/Analysis/LifetimeSafetyTest.cpp b/clang/unittests/Analysis/LifetimeSafetyTest.cpp new file mode 100644 index 0000000000000..b08159714e78a --- /dev/null +++ b/clang/unittests/Analysis/LifetimeSafetyTest.cpp @@ -0,0 +1,439 @@ +//===- LifetimeSafetyTest.cpp - Lifetime Safety Tests -*---------- 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 +// +//===----------------------------------------------------------------------===// + +#include "clang/Analysis/Analyses/LifetimeSafety.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Testing/TestAST.h" +#include "llvm/ADT/StringMap.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include +#include + +namespace clang::lifetimes::internal { +namespace { + +using namespace ast_matchers; +using ::testing::UnorderedElementsAreArray; + +// A helper class to run the full lifetime analysis on a piece of code +// and provide an interface for querying the results. +class LifetimeTestRunner { +public: + LifetimeTestRunner(llvm::StringRef Code) { + std::string FullCode = R"( + #define POINT(name) void("__lifetime_test_point_" #name) + struct MyObj { ~MyObj() {} int i; }; + )"; + FullCode += Code.str(); + + AST = std::make_unique(FullCode); + ASTCtx = &AST->context(); + + // Find the target function using AST matchers. + auto MatchResult = + match(functionDecl(hasName("target")).bind("target"), *ASTCtx); + auto *FD = selectFirst("target", MatchResult); + if (!FD) { + ADD_FAILURE() << "Test case must have a function named 'target'"; + return; + } + AnalysisCtx = std::make_unique(nullptr, FD); + AnalysisCtx->getCFGBuildOptions().setAllAlwaysAdd(); + + // Run the main analysis. + Analysis = std::make_unique(*AnalysisCtx); + Analysis->run(); + + AnnotationToPointMap = Analysis->getTestPoints(); + } + + LifetimeSafetyAnalysis &getAnalysis() { return *Analysis; } + ASTContext &getASTContext() { return *ASTCtx; } + + ProgramPoint getProgramPoint(llvm::StringRef Annotation) { + auto It = AnnotationToPointMap.find(Annotation); + if (It == AnnotationToPointMap.end()) { + ADD_FAILURE() << "Annotation '" << Annotation << "' not found."; + return nullptr; + } + return It->second; + } + +private: + std::unique_ptr AST; + ASTContext *ASTCtx = nullptr; + std::unique_ptr AnalysisCtx; + std::unique_ptr Analysis; + llvm::StringMap AnnotationToPointMap; +}; + +// A convenience wrapper that uses the LifetimeSafetyAnalysis public API. +class LifetimeTestHelper { +public: + LifetimeTestHelper(LifetimeTestRunner &Runner) + : Runner(Runner), Analysis(Runner.getAnalysis()) {} + + std::optional getOriginForDecl(llvm::StringRef VarName) { + auto *VD = findDecl(VarName); + if (!VD) + return std::nullopt; + auto OID = Analysis.getOriginIDForDecl(VD); + if (!OID) + ADD_FAILURE() << "Origin for '" << VarName << "' not found."; + return OID; + } + + std::optional getLoanForVar(llvm::StringRef VarName) { + auto *VD = findDecl(VarName); + if (!VD) + return std::nullopt; + std::vector LID = Analysis.getLoanIDForVar(VD); + if (LID.empty()) { + ADD_FAILURE() << "Loan for '" << VarName << "' not found."; + return std::nullopt; + } + // TODO: Support retrieving more than one loans to a var. + if (LID.size() > 1) { + ADD_FAILURE() << "More than 1 loans found for '" << VarName; + return std::nullopt; + } + return LID[0]; + } + + std::optional getLoansAtPoint(OriginID OID, + llvm::StringRef Annotation) { + ProgramPoint PP = Runner.getProgramPoint(Annotation); + if (!PP) + return std::nullopt; + return Analysis.getLoansAtPoint(OID, PP); + } + +private: + template DeclT *findDecl(llvm::StringRef Name) { + auto &Ctx = Runner.getASTContext(); + auto Results = match(valueDecl(hasName(Name)).bind("v"), Ctx); + if (Results.empty()) { + ADD_FAILURE() << "Declaration '" << Name << "' not found in AST."; + return nullptr; + } + return const_cast(selectFirst("v", Results)); + } + + LifetimeTestRunner &Runner; + LifetimeSafetyAnalysis &Analysis; +}; + +// ========================================================================= // +// GTest Matchers & Fixture +// ========================================================================= // + +// It holds the name of the origin variable and a reference to the helper. +class OriginInfo { +public: + OriginInfo(llvm::StringRef OriginVar, LifetimeTestHelper &Helper) + : OriginVar(OriginVar), Helper(Helper) {} + llvm::StringRef OriginVar; + LifetimeTestHelper &Helper; +}; + +/// Matcher to verify the set of loans held by an origin at a specific +/// program point. +/// +/// This matcher is intended to be used with an \c OriginInfo object. +/// +/// \param LoanVars A vector of strings, where each string is the name of a +/// variable expected to be the source of a loan. +/// \param Annotation A string identifying the program point (created with +/// POINT()) where the check should be performed. +MATCHER_P2(HasLoansToImpl, LoanVars, Annotation, "") { + const OriginInfo &Info = arg; + std::optional OIDOpt = Info.Helper.getOriginForDecl(Info.OriginVar); + if (!OIDOpt) { + *result_listener << "could not find origin for '" << Info.OriginVar.str() + << "'"; + return false; + } + + std::optional ActualLoansSetOpt = + Info.Helper.getLoansAtPoint(*OIDOpt, Annotation); + if (!ActualLoansSetOpt) { + *result_listener << "could not get a valid loan set at point '" + << Annotation << "'"; + return false; + } + std::vector ActualLoans(ActualLoansSetOpt->begin(), + ActualLoansSetOpt->end()); + + std::vector ExpectedLoans; + for (const auto &LoanVar : LoanVars) { + std::optional ExpectedLIDOpt = Info.Helper.getLoanForVar(LoanVar); + if (!ExpectedLIDOpt) { + *result_listener << "could not find loan for var '" << LoanVar << "'"; + return false; + } + ExpectedLoans.push_back(*ExpectedLIDOpt); + } + + return ExplainMatchResult(UnorderedElementsAreArray(ExpectedLoans), + ActualLoans, result_listener); +} + +// Base test fixture to manage the runner and helper. +class LifetimeAnalysisTest : public ::testing::Test { +protected: + void SetupTest(llvm::StringRef Code) { + Runner = std::make_unique(Code); + Helper = std::make_unique(*Runner); + } + + OriginInfo Origin(llvm::StringRef OriginVar) { + return OriginInfo(OriginVar, *Helper); + } + + // Factory function that hides the std::vector creation. + auto HasLoansTo(std::initializer_list LoanVars, + const char *Annotation) { + return HasLoansToImpl(std::vector(LoanVars), Annotation); + } + + std::unique_ptr Runner; + std::unique_ptr Helper; +}; + +// ========================================================================= // +// TESTS +// ========================================================================= // + +TEST_F(LifetimeAnalysisTest, SimpleLoanAndOrigin) { + SetupTest(R"( + void target() { + int x; + int* p = &x; + POINT(p1); + } + )"); + EXPECT_THAT(Origin("p"), HasLoansTo({"x"}, "p1")); +} + +TEST_F(LifetimeAnalysisTest, OverwriteOrigin) { + SetupTest(R"( + void target() { + MyObj s1, s2; + + MyObj* p = &s1; + POINT(after_s1); + + p = &s2; + POINT(after_s2); + } + )"); + EXPECT_THAT(Origin("p"), HasLoansTo({"s1"}, "after_s1")); + EXPECT_THAT(Origin("p"), HasLoansTo({"s2"}, "after_s2")); +} + +TEST_F(LifetimeAnalysisTest, ConditionalLoan) { + SetupTest(R"( + void target(bool cond) { + int a, b; + int *p = nullptr; + if (cond) { + p = &a; + POINT(after_then); + } else { + p = &b; + POINT(after_else); + } + POINT(after_if); + } + )"); + EXPECT_THAT(Origin("p"), HasLoansTo({"a"}, "after_then")); + EXPECT_THAT(Origin("p"), HasLoansTo({"b"}, "after_else")); + EXPECT_THAT(Origin("p"), HasLoansTo({"a", "b"}, "after_if")); +} + +TEST_F(LifetimeAnalysisTest, PointerChain) { + SetupTest(R"( + void target() { + MyObj y; + MyObj* ptr1 = &y; + POINT(p1); + + MyObj* ptr2 = ptr1; + POINT(p2); + + ptr2 = ptr1; + POINT(p3); + + ptr2 = ptr2; // Self assignment + POINT(p4); + } + )"); + EXPECT_THAT(Origin("ptr1"), HasLoansTo({"y"}, "p1")); + EXPECT_THAT(Origin("ptr2"), HasLoansTo({"y"}, "p2")); + EXPECT_THAT(Origin("ptr2"), HasLoansTo({"y"}, "p3")); + EXPECT_THAT(Origin("ptr2"), HasLoansTo({"y"}, "p4")); +} + +TEST_F(LifetimeAnalysisTest, ReassignToNull) { + SetupTest(R"( + void target() { + MyObj s1; + MyObj* p = &s1; + POINT(before_null); + p = nullptr; + POINT(after_null); + } + )"); + EXPECT_THAT(Origin("p"), HasLoansTo({"s1"}, "before_null")); + // After assigning to null, the origin for `p` should have no loans. + EXPECT_THAT(Origin("p"), HasLoansTo({}, "after_null")); +} + +TEST_F(LifetimeAnalysisTest, ReassignInIf) { + SetupTest(R"( + void target(bool condition) { + MyObj s1, s2; + MyObj* p = &s1; + POINT(before_if); + if (condition) { + p = &s2; + POINT(after_reassign); + } + POINT(after_if); + } + )"); + EXPECT_THAT(Origin("p"), HasLoansTo({"s1"}, "before_if")); + EXPECT_THAT(Origin("p"), HasLoansTo({"s2"}, "after_reassign")); + EXPECT_THAT(Origin("p"), HasLoansTo({"s1", "s2"}, "after_if")); +} + +TEST_F(LifetimeAnalysisTest, AssignInSwitch) { + SetupTest(R"( + void target(int mode) { + MyObj s1, s2, s3; + MyObj* p = nullptr; + switch (mode) { + case 1: + p = &s1; + POINT(case1); + break; + case 2: + p = &s2; + POINT(case2); + break; + default: + p = &s3; + POINT(case3); + break; + } + POINT(after_switch); + } + )"); + EXPECT_THAT(Origin("p"), HasLoansTo({"s1"}, "case1")); + EXPECT_THAT(Origin("p"), HasLoansTo({"s2"}, "case2")); + EXPECT_THAT(Origin("p"), HasLoansTo({"s3"}, "case3")); + EXPECT_THAT(Origin("p"), HasLoansTo({"s1", "s2", "s3"}, "after_switch")); +} + +TEST_F(LifetimeAnalysisTest, LoanInLoop) { + SetupTest(R"( + void target(bool condition) { + MyObj* p = nullptr; + while (condition) { + MyObj inner; + p = &inner; + POINT(in_loop); + } + POINT(after_loop); + } + )"); + EXPECT_THAT(Origin("p"), HasLoansTo({"inner"}, "in_loop")); + EXPECT_THAT(Origin("p"), HasLoansTo({"inner"}, "after_loop")); +} + +TEST_F(LifetimeAnalysisTest, LoopWithBreak) { + SetupTest(R"( + void target(int count) { + MyObj s1; + MyObj s2; + MyObj* p = &s1; + POINT(before_loop); + for (int i = 0; i < count; ++i) { + if (i == 5) { + p = &s2; + POINT(inside_if); + break; + } + POINT(after_if); + } + POINT(after_loop); + } + )"); + EXPECT_THAT(Origin("p"), HasLoansTo({"s1"}, "before_loop")); + EXPECT_THAT(Origin("p"), HasLoansTo({"s2"}, "inside_if")); + // At the join point after if, s2 cannot make it to p without the if. + EXPECT_THAT(Origin("p"), HasLoansTo({"s1"}, "after_if")); + // At the join point after the loop, p could hold a loan to s1 (if the loop + // completed normally) or to s2 (if the loop was broken). + EXPECT_THAT(Origin("p"), HasLoansTo({"s1", "s2"}, "after_loop")); +} + +TEST_F(LifetimeAnalysisTest, PointersInACycle) { + SetupTest(R"( + void target(bool condition) { + MyObj v1, v2, v3; + MyObj *p1 = &v1, *p2 = &v2, *p3 = &v3; + + POINT(before_while); + while (condition) { + MyObj* temp = p1; + p1 = p2; + p2 = p3; + p3 = temp; + } + POINT(after_loop); + } + )"); + EXPECT_THAT(Origin("p1"), HasLoansTo({"v1"}, "before_while")); + EXPECT_THAT(Origin("p2"), HasLoansTo({"v2"}, "before_while")); + EXPECT_THAT(Origin("p3"), HasLoansTo({"v3"}, "before_while")); + + // At the fixed point after the loop, all pointers could point to any of + // the three variables. + EXPECT_THAT(Origin("p1"), HasLoansTo({"v1", "v2", "v3"}, "after_loop")); + EXPECT_THAT(Origin("p2"), HasLoansTo({"v1", "v2", "v3"}, "after_loop")); + EXPECT_THAT(Origin("p3"), HasLoansTo({"v1", "v2", "v3"}, "after_loop")); + EXPECT_THAT(Origin("temp"), HasLoansTo({"v1", "v2", "v3"}, "after_loop")); +} + +TEST_F(LifetimeAnalysisTest, NestedScopes) { + SetupTest(R"( + void target() { + MyObj* p = nullptr; + { + MyObj outer; + p = &outer; + POINT(before_inner_scope); + { + MyObj inner; + p = &inner; + POINT(inside_inner_scope); + } // inner expires + POINT(after_inner_scope); + } // outer expires + } + )"); + EXPECT_THAT(Origin("p"), HasLoansTo({"outer"}, "before_inner_scope")); + EXPECT_THAT(Origin("p"), HasLoansTo({"inner"}, "inside_inner_scope")); + EXPECT_THAT(Origin("p"), HasLoansTo({"inner"}, "after_inner_scope")); +} + +} // anonymous namespace +} // namespace clang::lifetimes::internal diff --git a/clang/unittests/Format/BracesInserterTest.cpp b/clang/unittests/Format/BracesInserterTest.cpp index e0c447d671f45..572e53e595e37 100644 --- a/clang/unittests/Format/BracesInserterTest.cpp +++ b/clang/unittests/Format/BracesInserterTest.cpp @@ -257,9 +257,9 @@ TEST_F(BracesInserterTest, InsertBracesRange) { FormatStyle Style = getLLVMStyle(); Style.InsertBraces = true; - const StringRef Code("while (a)\n" - " if (b)\n" - " return;"); + constexpr StringRef Code("while (a)\n" + " if (b)\n" + " return;"); verifyFormat("while (a) {\n" " if (b)\n" diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index d17109aebc0f8..65d8b36c677bd 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -259,6 +259,7 @@ TEST(ConfigParseTest, ParsesConfigurationBools) { CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, Other); CHECK_PARSE_NESTED_BOOL(SortIncludes, Enabled); CHECK_PARSE_NESTED_BOOL(SortIncludes, IgnoreCase); + CHECK_PARSE_NESTED_BOOL(SortIncludes, IgnoreExtension); } #undef CHECK_PARSE_BOOL @@ -980,17 +981,20 @@ TEST(ConfigParseTest, ParsesConfiguration) { IncludeStyle.IncludeIsMainSourceRegex, "abc$"); Style.SortIncludes = {}; - CHECK_PARSE("SortIncludes: true", SortIncludes, - FormatStyle::SortIncludesOptions( - {/*Enabled=*/true, /*IgnoreCase=*/false})); + CHECK_PARSE( + "SortIncludes: true", SortIncludes, + FormatStyle::SortIncludesOptions( + {/*Enabled=*/true, /*IgnoreCase=*/false, /*IgnoreExtension=*/false})); CHECK_PARSE("SortIncludes: false", SortIncludes, FormatStyle::SortIncludesOptions({})); - CHECK_PARSE("SortIncludes: CaseInsensitive", SortIncludes, - FormatStyle::SortIncludesOptions( - {/*Enabled=*/true, /*IgnoreCase=*/true})); - CHECK_PARSE("SortIncludes: CaseSensitive", SortIncludes, - FormatStyle::SortIncludesOptions( - {/*Enabled=*/true, /*IgnoreCase=*/false})); + CHECK_PARSE( + "SortIncludes: CaseInsensitive", SortIncludes, + FormatStyle::SortIncludesOptions( + {/*Enabled=*/true, /*IgnoreCase=*/true, /*IgnoreExtension=*/false})); + CHECK_PARSE( + "SortIncludes: CaseSensitive", SortIncludes, + FormatStyle::SortIncludesOptions( + {/*Enabled=*/true, /*IgnoreCase=*/false, /*IgnoreExtension=*/false})); CHECK_PARSE("SortIncludes: Never", SortIncludes, FormatStyle::SortIncludesOptions({})); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 0bc1c6d45656e..dbf6950446ef0 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -3185,7 +3185,7 @@ TEST_F(FormatTest, FormatsLabels) { // The opening brace may either be on the same unwrapped line as the colon or // on a separate one. The formatter should recognize both. Style = getLLVMStyle(); - Style.BreakBeforeBraces = FormatStyle::BraceBreakingStyle::BS_Allman; + Style.BreakBeforeBraces = FormatStyle::BS_Allman; verifyFormat("{\n" " some_code();\n" "test_label:\n" @@ -3206,7 +3206,7 @@ TEST_F(FormatTest, FormatsLabels) { TEST_F(FormatTest, MultiLineControlStatements) { FormatStyle Style = getLLVMStyleWithColumns(20); - Style.BreakBeforeBraces = FormatStyle::BraceBreakingStyle::BS_Custom; + Style.BreakBeforeBraces = FormatStyle::BS_Custom; Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_MultiLine; // Short lines should keep opening brace on same line. verifyFormat("if (foo) {\n" @@ -3441,7 +3441,7 @@ TEST_F(FormatTest, MultiLineControlStatements) { TEST_F(FormatTest, BeforeWhile) { FormatStyle Style = getLLVMStyle(); - Style.BreakBeforeBraces = FormatStyle::BraceBreakingStyle::BS_Custom; + Style.BreakBeforeBraces = FormatStyle::BS_Custom; verifyFormat("do {\n" " foo();\n" @@ -4803,12 +4803,13 @@ TEST_F(FormatTest, FormatsInlineASM) { "int i;"); auto Style = getLLVMStyleWithColumns(0); - const StringRef Code1{"asm(\"xyz\" : \"=a\"(a), \"=d\"(b) : \"a\"(data));"}; - const StringRef Code2{"asm(\"xyz\"\n" - " : \"=a\"(a), \"=d\"(b)\n" - " : \"a\"(data));"}; - const StringRef Code3{"asm(\"xyz\" : \"=a\"(a), \"=d\"(b)\n" - " : \"a\"(data));"}; + constexpr StringRef Code1( + "asm(\"xyz\" : \"=a\"(a), \"=d\"(b) : \"a\"(data));"); + constexpr StringRef Code2("asm(\"xyz\"\n" + " : \"=a\"(a), \"=d\"(b)\n" + " : \"a\"(data));"); + constexpr StringRef Code3("asm(\"xyz\" : \"=a\"(a), \"=d\"(b)\n" + " : \"a\"(data));"); Style.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline; verifyFormat(Code1, Style); @@ -6681,6 +6682,17 @@ TEST_F(FormatTest, EscapedNewlines) { " int x(int a);", AlignLeft); + // Escaped with a trigraph. The program just has to avoid crashing. + verifyNoCrash("#define A \?\?/\n" + "int i;\?\?/\n" + " int j;"); + verifyNoCrash("#define A \?\?/\r\n" + "int i;\?\?/\r\n" + " int j;"); + verifyNoCrash("#define A \?\?/\n" + "int i;", + getGoogleStyle(FormatStyle::LK_CSharp)); + // CRLF line endings verifyFormat("#define A \\\r\n int i; \\\r\n int j;", "#define A \\\r\nint i;\\\r\n int j;", Narrow); @@ -6693,16 +6705,16 @@ TEST_F(FormatTest, EscapedNewlines) { " int x(int a);", AlignLeft); - constexpr StringRef Code{"#define A \\\n" + constexpr StringRef Code("#define A \\\n" " int a123; \\\n" " int a; \\\n" - " int a1234;"}; + " int a1234;"); verifyFormat(Code, AlignLeft); - constexpr StringRef Code2{"#define A \\\n" + constexpr StringRef Code2("#define A \\\n" " int a123; \\\n" " int a; \\\n" - " int a1234;"}; + " int a1234;"); auto LastLine = getLLVMStyle(); LastLine.AlignEscapedNewlines = FormatStyle::ENAS_LeftWithLastLine; verifyFormat(Code2, LastLine); @@ -12097,9 +12109,9 @@ TEST_F(FormatTest, PointerAlignmentFallback) { FormatStyle Style = getLLVMStyle(); Style.DerivePointerAlignment = true; - const StringRef Code("int* p;\n" - "int *q;\n" - "int * r;"); + constexpr StringRef Code("int* p;\n" + "int *q;\n" + "int * r;"); EXPECT_EQ(Style.PointerAlignment, FormatStyle::PAS_Right); verifyFormat("int *p;\n" @@ -15014,7 +15026,7 @@ TEST_F(FormatTest, PullTrivialFunctionDefinitionsIntoSingleLine) { " aaaaaaaaaaaaaaaaaa,\n" " aaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {}"); - constexpr StringRef Code{"void foo() { /* Empty */ }"}; + constexpr StringRef Code("void foo() { /* Empty */ }"); verifyFormat(Code); verifyFormat(Code, "void foo() { /* Empty */\n" "}"); @@ -23779,7 +23791,7 @@ TEST_F(FormatTest, FormatsLambdas) { LLVMWithBeforeLambdaBody.BreakBeforeBraces = FormatStyle::BS_Custom; LLVMWithBeforeLambdaBody.BraceWrapping.BeforeLambdaBody = true; LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine = - FormatStyle::ShortLambdaStyle::SLS_None; + FormatStyle::SLS_None; verifyFormat("FctWithOneNestedLambdaInline_SLS_None(\n" " []()\n" " {\n" @@ -23815,7 +23827,7 @@ TEST_F(FormatTest, FormatsLambdas) { LLVMWithBeforeLambdaBody); LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine = - FormatStyle::ShortLambdaStyle::SLS_Empty; + FormatStyle::SLS_Empty; verifyFormat("FctWithOneNestedLambdaInline_SLS_Empty(\n" " []()\n" " {\n" @@ -23862,7 +23874,7 @@ TEST_F(FormatTest, FormatsLambdas) { LLVMWithBeforeLambdaBody); LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine = - FormatStyle::ShortLambdaStyle::SLS_Inline; + FormatStyle::SLS_Inline; verifyFormat("FctWithOneNestedLambdaInline_SLS_Inline([]() { return 17; });", LLVMWithBeforeLambdaBody); verifyFormat("FctWithOneNestedLambdaEmpty_SLS_Inline([]() {});", @@ -23893,7 +23905,7 @@ TEST_F(FormatTest, FormatsLambdas) { LLVMWithBeforeLambdaBody); LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine = - FormatStyle::ShortLambdaStyle::SLS_All; + FormatStyle::SLS_All; verifyFormat("FctWithOneNestedLambdaInline_SLS_All([]() { return 17; });", LLVMWithBeforeLambdaBody); verifyFormat("FctWithOneNestedLambdaEmpty_SLS_All([]() {});", @@ -24025,7 +24037,7 @@ TEST_F(FormatTest, FormatsLambdas) { LLVMWithBeforeLambdaBody); LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine = - FormatStyle::ShortLambdaStyle::SLS_None; + FormatStyle::SLS_None; verifyFormat("auto select = [this]() -> const Library::Object *\n" "{\n" @@ -24273,7 +24285,7 @@ TEST_F(FormatTest, LambdaWithLineComments) { LLVMWithBeforeLambdaBody.BreakBeforeBraces = FormatStyle::BS_Custom; LLVMWithBeforeLambdaBody.BraceWrapping.BeforeLambdaBody = true; LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine = - FormatStyle::ShortLambdaStyle::SLS_All; + FormatStyle::SLS_All; verifyFormat("auto k = []() { return; }", LLVMWithBeforeLambdaBody); verifyFormat("auto k = []() // comment\n" @@ -27244,7 +27256,7 @@ TEST_F(FormatTest, IndentAccessModifiers) { TEST_F(FormatTest, LimitlessStringsAndComments) { auto Style = getLLVMStyleWithColumns(0); - constexpr StringRef Code = + constexpr StringRef Code( "/**\n" " * This is a multiline comment with quite some long lines, at least for " "the LLVM Style.\n" @@ -27265,7 +27277,7 @@ TEST_F(FormatTest, LimitlessStringsAndComments) { " const std::string SmallString = \"Hello World\";\n" " // Small line comment\n" " return String.size() > SmallString.size();\n" - "}"; + "}"); verifyNoChange(Code, Style); } @@ -28371,10 +28383,15 @@ TEST_F(FormatTest, BreakAfterAttributes) { "Foo &operator-(Foo &);", Style); - Style.ReferenceAlignment = FormatStyle::ReferenceAlignmentStyle::RAS_Left; + Style.ReferenceAlignment = FormatStyle::RAS_Left; verifyFormat("[[nodiscard]]\n" "Foo& operator-(Foo&);", Style); + + Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; + verifyFormat("[[deprecated]]\n" + "void f() = delete;", + Style); } TEST_F(FormatTest, InsertNewlineAtEOF) { @@ -28384,9 +28401,9 @@ TEST_F(FormatTest, InsertNewlineAtEOF) { verifyNoChange("int i;\n", Style); verifyFormat("int i;\n", "int i;", Style); - constexpr StringRef Code{"namespace {\n" + constexpr StringRef Code("namespace {\n" "int i;\n" - "} // namespace"}; + "} // namespace"); verifyFormat(Code.str() + '\n', Code, Style, {tooling::Range(19, 13)}); // line 3 } @@ -28395,7 +28412,7 @@ TEST_F(FormatTest, KeepEmptyLinesAtEOF) { FormatStyle Style = getLLVMStyle(); Style.KeepEmptyLines.AtEndOfFile = true; - const StringRef Code{"int i;\n\n"}; + constexpr StringRef Code("int i;\n\n"); verifyNoChange(Code, Style); verifyFormat(Code, "int i;\n\n\n", Style); } @@ -28628,8 +28645,8 @@ TEST_F(FormatTest, PPDirectivesAndCommentsInBracedInit) { } TEST_F(FormatTest, BreakAdjacentStringLiterals) { - constexpr StringRef Code{ - "return \"Code\" \"\\0\\52\\26\\55\\55\\0\" \"x013\" \"\\02\\xBA\";"}; + constexpr StringRef Code( + "return \"Code\" \"\\0\\52\\26\\55\\55\\0\" \"x013\" \"\\02\\xBA\";"); verifyFormat("return \"Code\"\n" " \"\\0\\52\\26\\55\\55\\0\"\n" @@ -29040,9 +29057,9 @@ TEST_F(FormatTest, KeepFormFeed) { auto Style = getLLVMStyle(); Style.KeepFormFeed = true; - constexpr StringRef NoFormFeed{"int i;\n" + constexpr StringRef NoFormFeed("int i;\n" "\n" - "void f();"}; + "void f();"); verifyFormat(NoFormFeed, "int i;\n" " \f\n" @@ -29064,9 +29081,9 @@ TEST_F(FormatTest, KeepFormFeed) { "void f();\f", Style); - constexpr StringRef FormFeed{"int i;\n" + constexpr StringRef FormFeed("int i;\n" "\f\n" - "void f();"}; + "void f();"); verifyNoChange(FormFeed, Style); Style.LineEnding = FormatStyle::LE_LF; @@ -29076,10 +29093,10 @@ TEST_F(FormatTest, KeepFormFeed) { "void f();", Style); - constexpr StringRef FormFeedBeforeEmptyLine{"int i;\n" + constexpr StringRef FormFeedBeforeEmptyLine("int i;\n" "\f\n" "\n" - "void f();"}; + "void f();"); Style.MaxEmptyLinesToKeep = 2; verifyFormat(FormFeedBeforeEmptyLine, "int i;\n" diff --git a/clang/unittests/Format/FormatTestComments.cpp b/clang/unittests/Format/FormatTestComments.cpp index 88707551b7698..69026bce98705 100644 --- a/clang/unittests/Format/FormatTestComments.cpp +++ b/clang/unittests/Format/FormatTestComments.cpp @@ -1120,11 +1120,11 @@ TEST_F(FormatTestComments, KeepsLevelOfCommentBeforePPDirective) { " }\n" "}")); - const StringRef Code("void func() {\n" - " // clang-format off\n" - " #define KV(value) #value, value\n" - " // clang-format on\n" - "}"); + constexpr StringRef Code("void func() {\n" + " // clang-format off\n" + " #define KV(value) #value, value\n" + " // clang-format on\n" + "}"); verifyNoChange(Code); auto Style = getLLVMStyle(); diff --git a/clang/unittests/Format/FormatTestJava.cpp b/clang/unittests/Format/FormatTestJava.cpp index ca5aba043b932..127556488bab0 100644 --- a/clang/unittests/Format/FormatTestJava.cpp +++ b/clang/unittests/Format/FormatTestJava.cpp @@ -631,17 +631,17 @@ TEST_F(FormatTestJava, SwitchExpression) { "});", Style); - constexpr StringRef Code1{"i = switch (day) {\n" + constexpr StringRef Code1("i = switch (day) {\n" " case THURSDAY, SATURDAY -> 8;\n" " case WEDNESDAY -> 9;\n" " default -> 0;\n" - "};"}; + "};"); verifyFormat(Code1, Style); Style.IndentCaseLabels = true; verifyFormat(Code1, Style); - constexpr StringRef Code2{"i = switch (day) {\n" + constexpr StringRef Code2("i = switch (day) {\n" " case THURSDAY, SATURDAY -> {\n" " foo();\n" " yield 8;\n" @@ -653,17 +653,17 @@ TEST_F(FormatTestJava, SwitchExpression) { " default -> {\n" " yield 0;\n" " }\n" - "};"}; + "};"); verifyFormat(Code2, Style); Style.IndentCaseLabels = false; verifyFormat(Code2, Style); - constexpr StringRef Code3{"switch (day) {\n" + constexpr StringRef Code3("switch (day) {\n" "case THURSDAY, SATURDAY -> i = 8;\n" "case WEDNESDAY -> i = 9;\n" "default -> i = 0;\n" - "};"}; + "};"); verifyFormat(Code3, Style); Style.IndentCaseLabels = true; diff --git a/clang/unittests/Format/FormatTestSelective.cpp b/clang/unittests/Format/FormatTestSelective.cpp index 0b7ac21fd33d3..1a01153a0af99 100644 --- a/clang/unittests/Format/FormatTestSelective.cpp +++ b/clang/unittests/Format/FormatTestSelective.cpp @@ -672,15 +672,14 @@ TEST_F(FormatTestSelective, FormatMacroRegardlessOfPreviousIndent) { // need to be adapted. Style = getLLVMStyle(); - const StringRef Code{" class Foo {\n" - " void test() {\n" - " #ifdef 1\n" - " #define some\n" // format this line - " #endif\n" - " }};"}; - - EXPECT_EQ(Style.IndentPPDirectives, - FormatStyle::PPDirectiveIndentStyle::PPDIS_None); + constexpr StringRef Code(" class Foo {\n" + " void test() {\n" + " #ifdef 1\n" + " #define some\n" // format this line + " #endif\n" + " }};"); + + EXPECT_EQ(Style.IndentPPDirectives, FormatStyle::PPDIS_None); EXPECT_EQ(" class Foo {\n" " void test() {\n" " #ifdef 1\n" @@ -689,8 +688,7 @@ TEST_F(FormatTestSelective, FormatMacroRegardlessOfPreviousIndent) { " }};", // Ditto: Bug? format(Code, 57, 0)); - Style.IndentPPDirectives = - FormatStyle::PPDirectiveIndentStyle::PPDIS_BeforeHash; + Style.IndentPPDirectives = FormatStyle::PPDIS_BeforeHash; EXPECT_EQ(" class Foo {\n" " void test() {\n" " #ifdef 1\n" @@ -699,8 +697,7 @@ TEST_F(FormatTestSelective, FormatMacroRegardlessOfPreviousIndent) { " }};", format(Code, 57, 0)); - Style.IndentPPDirectives = - FormatStyle::PPDirectiveIndentStyle::PPDIS_AfterHash; + Style.IndentPPDirectives = FormatStyle::PPDIS_AfterHash; EXPECT_EQ(" class Foo {\n" " void test() {\n" " #ifdef 1\n" diff --git a/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp b/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp index b1e42e924e05c..8681c3d2f89ce 100644 --- a/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp +++ b/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp @@ -24,7 +24,7 @@ TEST_F(IntegerLiteralSeparatorTest, SingleQuoteAsSeparator) { EXPECT_EQ(Style.IntegerLiteralSeparator.Decimal, 0); EXPECT_EQ(Style.IntegerLiteralSeparator.Hex, 0); - const StringRef Binary("b = 0b10011'11'0110'1u;"); + constexpr StringRef Binary("b = 0b10011'11'0110'1u;"); verifyFormat(Binary, Style); Style.IntegerLiteralSeparator.Binary = -1; verifyFormat("b = 0b100111101101u;", Binary, Style); @@ -33,14 +33,14 @@ TEST_F(IntegerLiteralSeparatorTest, SingleQuoteAsSeparator) { Style.IntegerLiteralSeparator.Binary = 4; verifyFormat("b = 0b1001'1110'1101u;", Binary, Style); - const StringRef Decimal("d = 184467'440737'0'95505'92Ull;"); + constexpr StringRef Decimal("d = 184467'440737'0'95505'92Ull;"); verifyFormat(Decimal, Style); Style.IntegerLiteralSeparator.Decimal = -1; verifyFormat("d = 18446744073709550592Ull;", Decimal, Style); Style.IntegerLiteralSeparator.Decimal = 3; verifyFormat("d = 18'446'744'073'709'550'592Ull;", Decimal, Style); - const StringRef Hex("h = 0xDEAD'BEEF'DE'AD'BEE'Fuz;"); + constexpr StringRef Hex("h = 0xDEAD'BEEF'DE'AD'BEE'Fuz;"); verifyFormat(Hex, Style); Style.IntegerLiteralSeparator.Hex = -1; verifyFormat("h = 0xDEADBEEFDEADBEEFuz;", Hex, Style); @@ -87,9 +87,9 @@ TEST_F(IntegerLiteralSeparatorTest, SingleQuoteAsSeparator) { TEST_F(IntegerLiteralSeparatorTest, UnderscoreAsSeparator) { FormatStyle Style = getLLVMStyle(); - const StringRef Binary("B = 0B10011_11_0110_1;"); - const StringRef Decimal("d = 184467_440737_0_95505_92;"); - const StringRef Hex("H = 0XDEAD_BEEF_DE_AD_BEE_F;"); + constexpr StringRef Binary("B = 0B10011_11_0110_1;"); + constexpr StringRef Decimal("d = 184467_440737_0_95505_92;"); + constexpr StringRef Hex("H = 0XDEAD_BEEF_DE_AD_BEE_F;"); auto TestUnderscore = [&](auto Language) { Style.Language = Language; @@ -173,16 +173,16 @@ TEST_F(IntegerLiteralSeparatorTest, FixRanges) { FormatStyle Style = getLLVMStyle(); Style.IntegerLiteralSeparator.Decimal = 3; - const StringRef Code("i = -12'34;\n" - "// clang-format off\n" - "j = 123'4;\n" - "// clang-format on\n" - "k = +1'23'4;"); - const StringRef Expected("i = -1'234;\n" + constexpr StringRef Code("i = -12'34;\n" "// clang-format off\n" "j = 123'4;\n" "// clang-format on\n" - "k = +1'234;"); + "k = +1'23'4;"); + constexpr StringRef Expected("i = -1'234;\n" + "// clang-format off\n" + "j = 123'4;\n" + "// clang-format on\n" + "k = +1'234;"); verifyFormat(Expected, Code, Style); diff --git a/clang/unittests/Format/SortIncludesTest.cpp b/clang/unittests/Format/SortIncludesTest.cpp index 994227efdd4f8..48ecd5d32d034 100644 --- a/clang/unittests/Format/SortIncludesTest.cpp +++ b/clang/unittests/Format/SortIncludesTest.cpp @@ -1084,10 +1084,10 @@ TEST_F(SortIncludesTest, DoNotSortLikelyXml) { } TEST_F(SortIncludesTest, DoNotSortCSharp) { - constexpr StringRef Code{"const string expectedDataStruct = @\"\n" + constexpr StringRef Code("const string expectedDataStruct = @\"\n" " #include \n" " #include \n" - " \";"}; + " \";"); FmtStyle.Language = FormatStyle::LK_CSharp; EXPECT_TRUE(sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a.cs").empty()); } @@ -1483,6 +1483,26 @@ TEST_F(SortIncludesTest, BlockCommentedOutIncludes) { verifyFormat(Code, sort(Code, "input.cpp", 0)); } +TEST_F(SortIncludesTest, IgnoreExtension) { + FmtStyle.SortIncludes.IgnoreExtension = true; + + verifyFormat("#include \n" + "#include \n" + "#include ", + sort("#include \n" + "#include \n" + "#include ", + "input.h")); + + verifyFormat("#include \n" + "#include \n" + "#include ", + sort("#include \n" + "#include \n" + "#include ", + "input.h")); +} + } // end namespace } // end namespace format } // end namespace clang diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index e281a4945a862..7f99655b1fa49 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -390,6 +390,10 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) { EXPECT_TOKEN(Tokens[20], tok::l_brace, TT_CompoundRequirementLBrace); EXPECT_TOKEN(Tokens[22], tok::star, TT_BinaryOperator); + Tokens = annotate("bool foo = requires { static_cast(1); };"); + ASSERT_EQ(Tokens.size(), 17u) << Tokens; + EXPECT_TOKEN(Tokens[8], tok::ampamp, TT_PointerOrReference); + Tokens = annotate("return s.operator int *();"); ASSERT_EQ(Tokens.size(), 10u) << Tokens; // Not TT_FunctionDeclarationName. @@ -614,7 +618,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsStructs) { EXPECT_TOKEN(Tokens[19], tok::l_brace, TT_StructLBrace); EXPECT_TOKEN(Tokens[20], tok::r_brace, TT_StructRBrace); - constexpr StringRef Code{"struct EXPORT StructName {};"}; + constexpr StringRef Code("struct EXPORT StructName {};"); Tokens = annotate(Code); ASSERT_EQ(Tokens.size(), 7u) << Tokens; @@ -3954,7 +3958,7 @@ TEST_F(TokenAnnotatorTest, SplitPenalty) { } TEST_F(TokenAnnotatorTest, TemplateName) { - constexpr StringRef Code{"return Foo < A || B > (C ^ D);"}; + constexpr StringRef Code("return Foo < A || B > (C ^ D);"); auto Tokens = annotate(Code); ASSERT_EQ(Tokens.size(), 14u) << Tokens; diff --git a/clang/unittests/Interpreter/InterpreterTest.cpp b/clang/unittests/Interpreter/InterpreterTest.cpp index b97f5ae17c9f0..2ba15cbd37093 100644 --- a/clang/unittests/Interpreter/InterpreterTest.cpp +++ b/clang/unittests/Interpreter/InterpreterTest.cpp @@ -22,6 +22,8 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/Sema.h" +#include "llvm/TargetParser/Host.h" + #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -389,6 +391,26 @@ TEST_F(InterpreterTest, Value) { EXPECT_TRUE(V9.getType()->isMemberFunctionPointerType()); EXPECT_EQ(V9.getKind(), Value::K_PtrOrObj); EXPECT_TRUE(V9.isManuallyAlloc()); + + Value V10; + llvm::cantFail(Interp->ParseAndExecute( + "enum D : unsigned int {Zero = 0, One}; One", &V10)); + + std::string prettyType; + llvm::raw_string_ostream OSType(prettyType); + V10.printType(OSType); + EXPECT_STREQ(prettyType.c_str(), "D"); + + // FIXME: We should print only the value or the constant not the type. + std::string prettyData; + llvm::raw_string_ostream OSData(prettyData); + V10.printData(OSData); + EXPECT_STREQ(prettyData.c_str(), "(One) : unsigned int 1"); + + std::string prettyPrint; + llvm::raw_string_ostream OSPrint(prettyPrint); + V10.print(OSPrint); + EXPECT_STREQ(prettyPrint.c_str(), "(D) (One) : unsigned int 1\n"); } TEST_F(InterpreterTest, TranslationUnit_CanonicalDecl) { diff --git a/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp b/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp index 46dbb4d4b91b4..ddc87921ea084 100644 --- a/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp +++ b/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp @@ -640,14 +640,14 @@ TEST(MinimizeSourceToDependencyDirectivesTest, AtImport) { EXPECT_STREQ("@import A;\n", Out.data()); ASSERT_FALSE(minimizeSourceToDependencyDirectives("@import A\n;", Out)); - EXPECT_STREQ("@import A;\n", Out.data()); + EXPECT_STREQ("@import A\n;\n", Out.data()); ASSERT_FALSE(minimizeSourceToDependencyDirectives("@import A.B;\n", Out)); EXPECT_STREQ("@import A.B;\n", Out.data()); ASSERT_FALSE(minimizeSourceToDependencyDirectives( - "@import /*x*/ A /*x*/ . /*x*/ B /*x*/ \n /*x*/ ; /*x*/", Out)); - EXPECT_STREQ("@import A.B;\n", Out.data()); + "@import /*x*/ A /*x*/ . /*x*/ B /*x*/ \\n /*x*/ ; /*x*/", Out)); + EXPECT_STREQ("@import A.B\\n;\n", Out.data()); } TEST(MinimizeSourceToDependencyDirectivesTest, EmptyIncludesAndImports) { @@ -1122,16 +1122,23 @@ ort \ )"; ASSERT_FALSE( minimizeSourceToDependencyDirectives(Source, Out, Tokens, Directives)); - EXPECT_STREQ("#include \"textual-header.h\"\nexport module m;" - "exp\\\nort import:l[[rename]];" - "import<<=3;import a b d e d e f e;" - "import foo[[no_unique_address]];import foo();" - "import f(:sefse);import f(->a=3);" + + EXPECT_STREQ("module;\n" + "#include \"textual-header.h\"\n" + "export module m;\n" + "exp\\\nort import:l[[rename]];\n" + "import<<=3;\n" + "import a b d e d e f e;\n" + "import foo[[no_unique_address]];\n" + "import foo();\n" + "import f(:sefse);\n" + "import f(->a=3);\n" "\n", Out.data()); - ASSERT_EQ(Directives.size(), 11u); - EXPECT_EQ(Directives[0].Kind, pp_include); - EXPECT_EQ(Directives[1].Kind, cxx_export_module_decl); + ASSERT_EQ(Directives.size(), 12u); + EXPECT_EQ(Directives[0].Kind, cxx_module_decl); + EXPECT_EQ(Directives[1].Kind, pp_include); + EXPECT_EQ(Directives[2].Kind, cxx_export_module_decl); } TEST(MinimizeSourceToDependencyDirectivesTest, ObjCMethodArgs) { diff --git a/clang/unittests/StaticAnalyzer/BlockEntranceCallbackTest.cpp b/clang/unittests/StaticAnalyzer/BlockEntranceCallbackTest.cpp index 0f05c39df93e0..d15bec02879f2 100644 --- a/clang/unittests/StaticAnalyzer/BlockEntranceCallbackTest.cpp +++ b/clang/unittests/StaticAnalyzer/BlockEntranceCallbackTest.cpp @@ -91,8 +91,7 @@ void addBlockEntranceTester(AnalysisASTConsumer &AnalysisConsumer, AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { Registry.addChecker(®isterChecker, &shouldAlwaysRegister, "test.BlockEntranceTester", - "EmptyDescription", "EmptyDocsUri", - /*IsHidden=*/false); + "EmptyDescription"); }); } @@ -102,8 +101,7 @@ void addBranchConditionTester(AnalysisASTConsumer &AnalysisConsumer, AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { Registry.addChecker(®isterChecker, &shouldAlwaysRegister, "test.BranchConditionTester", - "EmptyDescription", "EmptyDocsUri", - /*IsHidden=*/false); + "EmptyDescription"); }); } diff --git a/clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp b/clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp index 0ef63b049621e..fc50f0028015b 100644 --- a/clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp +++ b/clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp @@ -120,7 +120,7 @@ class TestAction : public ASTFrontendAction { std::move(ExpectedDiags), Compiler.getSourceManager())); AnalysisConsumer->AddCheckerRegistrationFn([](CheckerRegistry &Registry) { Registry.addChecker("test.Interestingness", - "Description", ""); + "MockDescription"); }); Compiler.getAnalyzerOpts().CheckersAndPackages = { {"test.Interestingness", true}}; diff --git a/clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp b/clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp index 4cb6bd34fa36d..e2007a9589c60 100644 --- a/clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp +++ b/clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp @@ -616,8 +616,8 @@ void addCallDescChecker(AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { AnOpts.CheckersAndPackages = {{"test.CallDescChecker", true}}; AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { - Registry.addChecker("test.CallDescChecker", "Description", - ""); + Registry.addChecker("test.CallDescChecker", + "MockDescription"); }); } diff --git a/clang/unittests/StaticAnalyzer/CallEventTest.cpp b/clang/unittests/StaticAnalyzer/CallEventTest.cpp index 2843572e5f800..8b5289ea7472b 100644 --- a/clang/unittests/StaticAnalyzer/CallEventTest.cpp +++ b/clang/unittests/StaticAnalyzer/CallEventTest.cpp @@ -56,7 +56,7 @@ void addCXXDeallocatorChecker(AnalysisASTConsumer &AnalysisConsumer, AnOpts.CheckersAndPackages = {{"test.CXXDeallocator", true}}; AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { Registry.addChecker("test.CXXDeallocator", - "Description", ""); + "MockDescription"); }); } diff --git a/clang/unittests/StaticAnalyzer/ConflictingEvalCallsTest.cpp b/clang/unittests/StaticAnalyzer/ConflictingEvalCallsTest.cpp index e410cca076637..cffdbf1896df3 100644 --- a/clang/unittests/StaticAnalyzer/ConflictingEvalCallsTest.cpp +++ b/clang/unittests/StaticAnalyzer/ConflictingEvalCallsTest.cpp @@ -33,10 +33,8 @@ void addEvalFooCheckers(AnalysisASTConsumer &AnalysisConsumer, AnOpts.CheckersAndPackages = {{"test.EvalFoo1", true}, {"test.EvalFoo2", true}}; AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { - Registry.addChecker("test.EvalFoo1", "EmptyDescription", - "EmptyDocsUri"); - Registry.addChecker("test.EvalFoo2", "EmptyDescription", - "EmptyDocsUri"); + Registry.addChecker("test.EvalFoo1", "MockDescription"); + Registry.addChecker("test.EvalFoo2", "MockDescription"); }); } } // namespace diff --git a/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp b/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp index b6eeb9ce37386..12be2289c3174 100644 --- a/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp +++ b/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp @@ -78,7 +78,7 @@ void addExprEngineVisitPreChecker(AnalysisASTConsumer &AnalysisConsumer, AnOpts.CheckersAndPackages = {{"ExprEngineVisitPreChecker", true}}; AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { Registry.addChecker("ExprEngineVisitPreChecker", - "Desc", "DocsURI"); + "MockDescription"); }); } @@ -87,7 +87,7 @@ void addExprEngineVisitPostChecker(AnalysisASTConsumer &AnalysisConsumer, AnOpts.CheckersAndPackages = {{"ExprEngineVisitPostChecker", true}}; AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { Registry.addChecker( - "ExprEngineVisitPostChecker", "Desc", "DocsURI"); + "ExprEngineVisitPostChecker", "MockDescription"); }); } @@ -95,8 +95,8 @@ void addMemAccessChecker(AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { AnOpts.CheckersAndPackages = {{"MemAccessChecker", true}}; AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { - Registry.addChecker("MemAccessChecker", "Desc", - "DocsURI"); + Registry.addChecker("MemAccessChecker", + "MockDescription"); }); } diff --git a/clang/unittests/StaticAnalyzer/FalsePositiveRefutationBRVisitorTest.cpp b/clang/unittests/StaticAnalyzer/FalsePositiveRefutationBRVisitorTest.cpp index 8f0a96d41e752..146797f5b17f2 100644 --- a/clang/unittests/StaticAnalyzer/FalsePositiveRefutationBRVisitorTest.cpp +++ b/clang/unittests/StaticAnalyzer/FalsePositiveRefutationBRVisitorTest.cpp @@ -92,8 +92,8 @@ void addFalsePositiveGenerator(AnalysisASTConsumer &AnalysisConsumer, AnOpts.CheckersAndPackages = {{"test.FalsePositiveGenerator", true}, {"debug.ViewExplodedGraph", false}}; AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { - Registry.addChecker( - "test.FalsePositiveGenerator", "EmptyDescription", "EmptyDocsUri"); + Registry.addChecker("test.FalsePositiveGenerator", + "MockDescription"); }); } diff --git a/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp b/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp index 0f6e49bf42f4a..7b837f3b7fb2a 100644 --- a/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp +++ b/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp @@ -46,7 +46,7 @@ void addDescriptiveNameChecker(AnalysisASTConsumer &AnalysisConsumer, AnOpts.CheckersAndPackages = {{"DescriptiveNameChecker", true}}; AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { Registry.addChecker("DescriptiveNameChecker", - "Desc", "DocsURI"); + "MockDescription"); }); } diff --git a/clang/unittests/StaticAnalyzer/NoStateChangeFuncVisitorTest.cpp b/clang/unittests/StaticAnalyzer/NoStateChangeFuncVisitorTest.cpp index a9033425dfb51..68d267853e926 100644 --- a/clang/unittests/StaticAnalyzer/NoStateChangeFuncVisitorTest.cpp +++ b/clang/unittests/StaticAnalyzer/NoStateChangeFuncVisitorTest.cpp @@ -140,7 +140,7 @@ void addNonThoroughStatefulChecker(AnalysisASTConsumer &AnalysisConsumer, AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { Registry .addChecker>( - "test.StatefulChecker", "Description", ""); + "test.StatefulChecker", "MockDescription"); }); } @@ -233,7 +233,7 @@ void addThoroughStatefulChecker(AnalysisASTConsumer &AnalysisConsumer, AnOpts.CheckersAndPackages = {{"test.StatefulChecker", true}}; AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { Registry.addChecker>( - "test.StatefulChecker", "Description", ""); + "test.StatefulChecker", "MockDescription"); }); } diff --git a/clang/unittests/StaticAnalyzer/ObjcBug-124477.cpp b/clang/unittests/StaticAnalyzer/ObjcBug-124477.cpp index 51bd33210032c..ab78090b42f31 100644 --- a/clang/unittests/StaticAnalyzer/ObjcBug-124477.cpp +++ b/clang/unittests/StaticAnalyzer/ObjcBug-124477.cpp @@ -37,7 +37,7 @@ void addFlagFlipperChecker(AnalysisASTConsumer &AnalysisConsumer, AnOpts.CheckersAndPackages = {{"test.FlipFlagOnCheckLocation", true}}; AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { Registry.addChecker("test.FlipFlagOnCheckLocation", - "Description", ""); + "MockDescription"); }); } diff --git a/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp b/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp index 454eee9cf7e0a..e17d107d90cef 100644 --- a/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp +++ b/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp @@ -44,7 +44,7 @@ void addCustomChecker(AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { AnOpts.CheckersAndPackages = {{"test.CustomChecker", true}}; AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { - Registry.addChecker("test.CustomChecker", "Description", ""); + Registry.addChecker("test.CustomChecker", "MockDescription"); }); } @@ -73,8 +73,8 @@ void addLocIncDecChecker(AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { AnOpts.CheckersAndPackages = {{"test.LocIncDecChecker", true}}; AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { - Registry.addChecker("test.LocIncDecChecker", "Description", - ""); + Registry.addChecker("test.LocIncDecChecker", + "MockDescription"); }); } @@ -119,10 +119,10 @@ bool shouldRegisterCheckerRegistrationOrderPrinter(const CheckerManager &mgr) { void addCheckerRegistrationOrderPrinter(CheckerRegistry &Registry) { Registry.addChecker(registerCheckerRegistrationOrderPrinter, shouldRegisterCheckerRegistrationOrderPrinter, - "test.RegistrationOrder", "Description", "", false); + "test.RegistrationOrder", "Description"); } -#define UNITTEST_CHECKER(CHECKER_NAME, DIAG_MSG) \ +#define UNITTEST_CHECKER(CHECKER_NAME) \ class CHECKER_NAME : public Checker> { \ public: \ void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {} \ @@ -137,11 +137,11 @@ void addCheckerRegistrationOrderPrinter(CheckerRegistry &Registry) { } \ void add##CHECKER_NAME(CheckerRegistry &Registry) { \ Registry.addChecker(register##CHECKER_NAME, shouldRegister##CHECKER_NAME, \ - "test." #CHECKER_NAME, "Description", "", false); \ + "test." #CHECKER_NAME, "Description"); \ } -UNITTEST_CHECKER(StrongDep, "Strong") -UNITTEST_CHECKER(Dep, "Dep") +UNITTEST_CHECKER(StrongDep) +UNITTEST_CHECKER(Dep) bool shouldRegisterStrongFALSE(const CheckerManager &mgr) { return false; @@ -154,7 +154,7 @@ void addDep(AnalysisASTConsumer &AnalysisConsumer, {"test.RegistrationOrder", true}}; AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { Registry.addChecker(registerStrongDep, shouldRegisterStrongFALSE, - "test.Strong", "Description", "", false); + "test.Strong", "Description"); addStrongDep(Registry); addDep(Registry); addCheckerRegistrationOrderPrinter(Registry); @@ -172,7 +172,7 @@ TEST(RegisterDeps, UnsatisfiedDependency) { // Weak checker dependencies. //===----------------------------------------------------------------------===// -UNITTEST_CHECKER(WeakDep, "Weak") +UNITTEST_CHECKER(WeakDep) void addWeakDepCheckerBothEnabled(AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { @@ -225,8 +225,8 @@ void addWeakDepCheckerDepUnspecified(AnalysisASTConsumer &AnalysisConsumer, }); } -UNITTEST_CHECKER(WeakDep2, "Weak2") -UNITTEST_CHECKER(Dep2, "Dep2") +UNITTEST_CHECKER(WeakDep2) +UNITTEST_CHECKER(Dep2) void addWeakDepHasWeakDep(AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { diff --git a/clang/unittests/StaticAnalyzer/SValSimplifyerTest.cpp b/clang/unittests/StaticAnalyzer/SValSimplifyerTest.cpp index 85cfe2c1965ac..4331ffc1b585c 100644 --- a/clang/unittests/StaticAnalyzer/SValSimplifyerTest.cpp +++ b/clang/unittests/StaticAnalyzer/SValSimplifyerTest.cpp @@ -68,8 +68,7 @@ static void addSimplifyChecker(AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { AnOpts.CheckersAndPackages = {{"SimplifyChecker", true}}; AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { - Registry.addChecker("SimplifyChecker", "EmptyDescription", - "EmptyDocsUri"); + Registry.addChecker("SimplifyChecker", "MockDescription"); }); } diff --git a/clang/unittests/StaticAnalyzer/SValTest.cpp b/clang/unittests/StaticAnalyzer/SValTest.cpp index d8897b0f2183d..58e9a8da0e99d 100644 --- a/clang/unittests/StaticAnalyzer/SValTest.cpp +++ b/clang/unittests/StaticAnalyzer/SValTest.cpp @@ -139,10 +139,10 @@ class SValTest : public testing::TestWithParam {}; \ void add##NAME##SValCollector(AnalysisASTConsumer &AnalysisConsumer, \ AnalyzerOptions &AnOpts) { \ - AnOpts.CheckersAndPackages = {{"test.##NAME##SValCollector", true}}; \ + AnOpts.CheckersAndPackages = {{"test." #NAME "SValColl", true}}; \ AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { \ - Registry.addChecker("test.##NAME##SValCollector", \ - "Description", ""); \ + Registry.addChecker("test." #NAME "SValColl", \ + "MockDescription"); \ }); \ } \ \ diff --git a/clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp b/clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp index 5fc084a48667c..0cb3c59a4421d 100644 --- a/clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp +++ b/clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp @@ -49,9 +49,9 @@ void addTestReturnValueUnderConstructionChecker( AnOpts.CheckersAndPackages = {{"test.TestReturnValueUnderConstruction", true}}; AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { - Registry.addChecker( - "test.TestReturnValueUnderConstruction", "", ""); - }); + Registry.addChecker( + "test.TestReturnValueUnderConstruction", "MockDescription"); + }); } TEST(TestReturnValueUnderConstructionChecker, diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp index ddc663e2b6fd3..23a2df42ff08c 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp @@ -25,8 +25,8 @@ class NestedNameSpecifiersVisitor : public ExpectedLocationVisitor { bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) override { if (!NNS) return true; - if (const NamespaceDecl *ND = - NNS.getNestedNameSpecifier()->getAsNamespace()) + if (const auto *ND = dyn_cast_if_present( + NNS.getNestedNameSpecifier()->getAsNamespace())) Match(ND->getName(), NNS.getLocalBeginLoc()); return ExpectedLocationVisitor::TraverseNestedNameSpecifierLoc(NNS); } diff --git a/clang/unittests/Tooling/RefactoringTest.cpp b/clang/unittests/Tooling/RefactoringTest.cpp index 254d95bc20cb0..35d114343b517 100644 --- a/clang/unittests/Tooling/RefactoringTest.cpp +++ b/clang/unittests/Tooling/RefactoringTest.cpp @@ -748,7 +748,8 @@ class NestedNameSpecifierAVisitor : public TestVisitor { public: bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLoc) override { if (NNSLoc.getNestedNameSpecifier()) { - if (const NamespaceDecl* NS = NNSLoc.getNestedNameSpecifier()->getAsNamespace()) { + if (const auto *NS = dyn_cast_if_present( + NNSLoc.getNestedNameSpecifier()->getAsNamespace())) { if (NS->getName() == "a") { Replace = Replacement(*SM, &NNSLoc, "", Context->getLangOpts()); } diff --git a/compiler-rt/lib/asan/asan_allocator.cpp b/compiler-rt/lib/asan/asan_allocator.cpp index d3c0288285b86..9ebe4d08ec8c1 100644 --- a/compiler-rt/lib/asan/asan_allocator.cpp +++ b/compiler-rt/lib/asan/asan_allocator.cpp @@ -1007,13 +1007,8 @@ void PrintInternalAllocatorStats() { instance.PrintStats(); } -void asan_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type) { - instance.Deallocate(ptr, 0, 0, stack, alloc_type); -} - -void asan_delete(void *ptr, uptr size, uptr alignment, - BufferedStackTrace *stack, AllocType alloc_type) { - instance.Deallocate(ptr, size, alignment, stack, alloc_type); +void asan_free(void *ptr, BufferedStackTrace *stack) { + instance.Deallocate(ptr, 0, 0, stack, FROM_MALLOC); } void *asan_malloc(uptr size, BufferedStackTrace *stack) { @@ -1068,8 +1063,7 @@ void *asan_pvalloc(uptr size, BufferedStackTrace *stack) { instance.Allocate(size, PageSize, stack, FROM_MALLOC, true)); } -void *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack, - AllocType alloc_type) { +void *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack) { if (UNLIKELY(!IsPowerOfTwo(alignment))) { errno = errno_EINVAL; if (AllocatorMayReturnNull()) @@ -1077,7 +1071,7 @@ void *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack, ReportInvalidAllocationAlignment(alignment, stack); } return SetErrnoOnNull( - instance.Allocate(size, alignment, stack, alloc_type, true)); + instance.Allocate(size, alignment, stack, FROM_MALLOC, true)); } void *asan_aligned_alloc(uptr alignment, uptr size, BufferedStackTrace *stack) { @@ -1117,6 +1111,99 @@ uptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr bp) { return usable_size; } +namespace { + +void *asan_new(uptr size, BufferedStackTrace *stack, bool array) { + return SetErrnoOnNull( + instance.Allocate(size, 0, stack, array ? FROM_NEW_BR : FROM_NEW, true)); +} + +void *asan_new_aligned(uptr size, uptr alignment, BufferedStackTrace *stack, + bool array) { + if (UNLIKELY(alignment == 0 || !IsPowerOfTwo(alignment))) { + errno = errno_EINVAL; + if (AllocatorMayReturnNull()) + return nullptr; + ReportInvalidAllocationAlignment(alignment, stack); + } + return SetErrnoOnNull(instance.Allocate( + size, alignment, stack, array ? FROM_NEW_BR : FROM_NEW, true)); +} + +void asan_delete(void *ptr, BufferedStackTrace *stack, bool array) { + instance.Deallocate(ptr, 0, 0, stack, array ? FROM_NEW_BR : FROM_NEW); +} + +void asan_delete_aligned(void *ptr, uptr alignment, BufferedStackTrace *stack, + bool array) { + instance.Deallocate(ptr, 0, alignment, stack, array ? FROM_NEW_BR : FROM_NEW); +} + +void asan_delete_sized(void *ptr, uptr size, BufferedStackTrace *stack, + bool array) { + instance.Deallocate(ptr, size, 0, stack, array ? FROM_NEW_BR : FROM_NEW); +} + +void asan_delete_sized_aligned(void *ptr, uptr size, uptr alignment, + BufferedStackTrace *stack, bool array) { + instance.Deallocate(ptr, size, alignment, stack, + array ? FROM_NEW_BR : FROM_NEW); +} + +} // namespace + +void *asan_new(uptr size, BufferedStackTrace *stack) { + return asan_new(size, stack, /*array=*/false); +} + +void *asan_new_aligned(uptr size, uptr alignment, BufferedStackTrace *stack) { + return asan_new_aligned(size, alignment, stack, /*array=*/false); +} + +void *asan_new_array(uptr size, BufferedStackTrace *stack) { + return asan_new(size, stack, /*array=*/true); +} + +void *asan_new_array_aligned(uptr size, uptr alignment, + BufferedStackTrace *stack) { + return asan_new_aligned(size, alignment, stack, /*array=*/true); +} + +void asan_delete(void *ptr, BufferedStackTrace *stack) { + asan_delete(ptr, stack, /*array=*/false); +} + +void asan_delete_aligned(void *ptr, uptr alignment, BufferedStackTrace *stack) { + asan_delete_aligned(ptr, alignment, stack, /*array=*/false); +} + +void asan_delete_sized(void *ptr, uptr size, BufferedStackTrace *stack) { + asan_delete_sized(ptr, size, stack, /*array=*/false); +} + +void asan_delete_sized_aligned(void *ptr, uptr size, uptr alignment, + BufferedStackTrace *stack) { + asan_delete_sized_aligned(ptr, size, alignment, stack, /*array=*/false); +} + +void asan_delete_array(void *ptr, BufferedStackTrace *stack) { + asan_delete(ptr, stack, /*array=*/true); +} + +void asan_delete_array_aligned(void *ptr, uptr alignment, + BufferedStackTrace *stack) { + asan_delete_aligned(ptr, alignment, stack, /*array=*/true); +} + +void asan_delete_array_sized(void *ptr, uptr size, BufferedStackTrace *stack) { + asan_delete_sized(ptr, size, stack, /*array=*/true); +} + +void asan_delete_array_sized_aligned(void *ptr, uptr size, uptr alignment, + BufferedStackTrace *stack) { + asan_delete_sized_aligned(ptr, size, alignment, stack, /*array=*/true); +} + uptr asan_mz_size(const void *ptr) { return instance.AllocationSize(reinterpret_cast(ptr)); } diff --git a/compiler-rt/lib/asan/asan_allocator.h b/compiler-rt/lib/asan/asan_allocator.h index 247d8bb77c984..fdf456473fb02 100644 --- a/compiler-rt/lib/asan/asan_allocator.h +++ b/compiler-rt/lib/asan/asan_allocator.h @@ -270,11 +270,8 @@ struct AsanThreadLocalMallocStorage { AsanThreadLocalMallocStorage() {} }; -void *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack, - AllocType alloc_type); -void asan_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type); -void asan_delete(void *ptr, uptr size, uptr alignment, - BufferedStackTrace *stack, AllocType alloc_type); +void *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack); +void asan_free(void *ptr, BufferedStackTrace *stack); void *asan_malloc(uptr size, BufferedStackTrace *stack); void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack); @@ -289,6 +286,23 @@ int asan_posix_memalign(void **memptr, uptr alignment, uptr size, BufferedStackTrace *stack); uptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr bp); +void *asan_new(uptr size, BufferedStackTrace *stack); +void *asan_new_aligned(uptr size, uptr alignment, BufferedStackTrace *stack); +void *asan_new_array(uptr size, BufferedStackTrace *stack); +void *asan_new_array_aligned(uptr size, uptr alignment, + BufferedStackTrace *stack); +void asan_delete(void *ptr, BufferedStackTrace *stack); +void asan_delete_aligned(void *ptr, uptr alignment, BufferedStackTrace *stack); +void asan_delete_sized(void *ptr, uptr size, BufferedStackTrace *stack); +void asan_delete_sized_aligned(void *ptr, uptr size, uptr alignment, + BufferedStackTrace *stack); +void asan_delete_array(void *ptr, BufferedStackTrace *stack); +void asan_delete_array_aligned(void *ptr, uptr alignment, + BufferedStackTrace *stack); +void asan_delete_array_sized(void *ptr, uptr size, BufferedStackTrace *stack); +void asan_delete_array_sized_aligned(void *ptr, uptr size, uptr alignment, + BufferedStackTrace *stack); + uptr asan_mz_size(const void *ptr); void asan_mz_force_lock(); void asan_mz_force_unlock(); diff --git a/compiler-rt/lib/asan/asan_descriptions.cpp b/compiler-rt/lib/asan/asan_descriptions.cpp index 0c30959b23e28..18c2a6c571c1f 100644 --- a/compiler-rt/lib/asan/asan_descriptions.cpp +++ b/compiler-rt/lib/asan/asan_descriptions.cpp @@ -449,10 +449,12 @@ AddressDescription::AddressDescription(uptr addr, uptr access_size, // are put to the STACK region for unknown reasons. Check global first can // workaround this issue. // TODO: Look into whether there's a different solution to this problem. +#if SANITIZER_AIX if (GetGlobalAddressInformation(addr, access_size, &data.global)) { data.kind = kAddressKindGlobal; return; } +#endif if (GetHeapAddressInformation(addr, access_size, &data.heap)) { data.kind = kAddressKindHeap; @@ -471,6 +473,14 @@ AddressDescription::AddressDescription(uptr addr, uptr access_size, return; } +// GetGlobalAddressInformation is called earlier on AIX due to a workaround +#if !SANITIZER_AIX + if (GetGlobalAddressInformation(addr, access_size, &data.global)) { + data.kind = kAddressKindGlobal; + return; + } +#endif + data.kind = kAddressKindWild; data.wild.addr = addr; data.wild.access_size = access_size; diff --git a/compiler-rt/lib/asan/asan_mac.cpp b/compiler-rt/lib/asan/asan_mac.cpp index be513a03ed5cd..4bc2c88e7d88a 100644 --- a/compiler-rt/lib/asan/asan_mac.cpp +++ b/compiler-rt/lib/asan/asan_mac.cpp @@ -176,7 +176,7 @@ void asan_dispatch_call_block_and_release(void *block) { asan_register_worker_thread(context->parent_tid, &stack); // Call the original dispatcher for the block. context->func(context->block); - asan_free(context, &stack, FROM_MALLOC); + asan_free(context, &stack); } } // namespace __asan diff --git a/compiler-rt/lib/asan/asan_malloc_linux.cpp b/compiler-rt/lib/asan/asan_malloc_linux.cpp index 3f023d4c2ed0a..add57318785be 100644 --- a/compiler-rt/lib/asan/asan_malloc_linux.cpp +++ b/compiler-rt/lib/asan/asan_malloc_linux.cpp @@ -49,7 +49,7 @@ INTERCEPTOR(void, free, void *ptr) { if (DlsymAlloc::PointerIsMine(ptr)) return DlsymAlloc::Free(ptr); GET_STACK_TRACE_FREE; - asan_free(ptr, &stack, FROM_MALLOC); + asan_free(ptr, &stack); } #if SANITIZER_INTERCEPT_CFREE @@ -57,7 +57,7 @@ INTERCEPTOR(void, cfree, void *ptr) { if (DlsymAlloc::PointerIsMine(ptr)) return DlsymAlloc::Free(ptr); GET_STACK_TRACE_FREE; - asan_free(ptr, &stack, FROM_MALLOC); + asan_free(ptr, &stack); } #endif // SANITIZER_INTERCEPT_CFREE @@ -93,12 +93,12 @@ INTERCEPTOR(void*, reallocarray, void *ptr, uptr nmemb, uptr size) { #if SANITIZER_INTERCEPT_MEMALIGN INTERCEPTOR(void*, memalign, uptr boundary, uptr size) { GET_STACK_TRACE_MALLOC; - return asan_memalign(boundary, size, &stack, FROM_MALLOC); + return asan_memalign(boundary, size, &stack); } INTERCEPTOR(void*, __libc_memalign, uptr boundary, uptr size) { GET_STACK_TRACE_MALLOC; - return asan_memalign(boundary, size, &stack, FROM_MALLOC); + return asan_memalign(boundary, size, &stack); } #endif // SANITIZER_INTERCEPT_MEMALIGN diff --git a/compiler-rt/lib/asan/asan_malloc_mac.cpp b/compiler-rt/lib/asan/asan_malloc_mac.cpp index f25d7e1901536..a442bdbbaa4d3 100644 --- a/compiler-rt/lib/asan/asan_malloc_mac.cpp +++ b/compiler-rt/lib/asan/asan_malloc_mac.cpp @@ -31,7 +31,7 @@ using namespace __asan; # define COMMON_MALLOC_FORCE_UNLOCK() asan_mz_force_unlock() # define COMMON_MALLOC_MEMALIGN(alignment, size) \ GET_STACK_TRACE_MALLOC; \ - void *p = asan_memalign(alignment, size, &stack, FROM_MALLOC) + void *p = asan_memalign(alignment, size, &stack) # define COMMON_MALLOC_MALLOC(size) \ GET_STACK_TRACE_MALLOC; \ void *p = asan_malloc(size, &stack) @@ -46,10 +46,10 @@ using namespace __asan; int res = asan_posix_memalign(memptr, alignment, size, &stack); # define COMMON_MALLOC_VALLOC(size) \ GET_STACK_TRACE_MALLOC; \ - void *p = asan_memalign(GetPageSizeCached(), size, &stack, FROM_MALLOC); + void *p = asan_memalign(GetPageSizeCached(), size, &stack); # define COMMON_MALLOC_FREE(ptr) \ GET_STACK_TRACE_FREE; \ - asan_free(ptr, &stack, FROM_MALLOC); + asan_free(ptr, &stack); # define COMMON_MALLOC_SIZE(ptr) uptr size = asan_mz_size(ptr); # define COMMON_MALLOC_FILL_STATS(zone, stats) \ AsanMallocStats malloc_stats; \ diff --git a/compiler-rt/lib/asan/asan_malloc_win.cpp b/compiler-rt/lib/asan/asan_malloc_win.cpp index 3278f07219876..8d98da940800f 100644 --- a/compiler-rt/lib/asan/asan_malloc_win.cpp +++ b/compiler-rt/lib/asan/asan_malloc_win.cpp @@ -69,7 +69,7 @@ __declspec(noinline) size_t _msize_base(void *ptr) { return _msize(ptr); } __declspec(noinline) void free(void *ptr) { GET_STACK_TRACE_FREE; - return asan_free(ptr, &stack, FROM_MALLOC); + return asan_free(ptr, &stack); } __declspec(noinline) void _free_dbg(void *ptr, int) { free(ptr); } @@ -252,7 +252,7 @@ INTERCEPTOR_WINAPI(BOOL, HeapFree, HANDLE hHeap, DWORD dwFlags, LPVOID lpMem) { CHECK((HEAP_FREE_UNSUPPORTED_FLAGS & dwFlags) != 0 && "unsupported flags"); } GET_STACK_TRACE_FREE; - asan_free(lpMem, &stack, FROM_MALLOC); + asan_free(lpMem, &stack); return true; } @@ -306,7 +306,7 @@ void *SharedReAlloc(ReAllocFunction reallocFunc, SizeFunction heapSizeFunc, if (replacement_alloc) { size_t old_size = heapSizeFunc(hHeap, dwFlags, lpMem); if (old_size == ((size_t)0) - 1) { - asan_free(replacement_alloc, &stack, FROM_MALLOC); + asan_free(replacement_alloc, &stack); return nullptr; } REAL(memcpy)(replacement_alloc, lpMem, old_size); @@ -331,7 +331,7 @@ void *SharedReAlloc(ReAllocFunction reallocFunc, SizeFunction heapSizeFunc, old_usable_size = asan_malloc_usable_size(lpMem, pc, bp); REAL(memcpy)(replacement_alloc, lpMem, Min(dwBytes, old_usable_size)); - asan_free(lpMem, &stack, FROM_MALLOC); + asan_free(lpMem, &stack); } return replacement_alloc; } @@ -429,7 +429,7 @@ INTERCEPTOR_WINAPI(BOOL, RtlFreeHeap, HANDLE HeapHandle, DWORD Flags, return REAL(RtlFreeHeap)(HeapHandle, Flags, BaseAddress); } GET_STACK_TRACE_FREE; - asan_free(BaseAddress, &stack, FROM_MALLOC); + asan_free(BaseAddress, &stack); return true; } diff --git a/compiler-rt/lib/asan/asan_new_delete.cpp b/compiler-rt/lib/asan/asan_new_delete.cpp index 99c7c9938dfb3..d7ed5b570728b 100644 --- a/compiler-rt/lib/asan/asan_new_delete.cpp +++ b/compiler-rt/lib/asan/asan_new_delete.cpp @@ -60,42 +60,42 @@ enum class align_val_t: size_t {}; // TODO(alekseyshl): throw std::bad_alloc instead of dying on OOM. // For local pool allocation, align to SHADOW_GRANULARITY to match asan // allocator behavior. -#define OPERATOR_NEW_BODY \ - GET_STACK_TRACE_MALLOC; \ - void *res = asan_memalign(0, size, &stack, FROM_NEW); \ - if (UNLIKELY(!res)) \ - ReportOutOfMemory(size, &stack); \ +#define OPERATOR_NEW_BODY \ + GET_STACK_TRACE_MALLOC; \ + void *res = asan_new(size, &stack); \ + if (UNLIKELY(!res)) \ + ReportOutOfMemory(size, &stack); \ return res #define OPERATOR_NEW_BODY_NOTHROW \ GET_STACK_TRACE_MALLOC; \ - return asan_memalign(0, size, &stack, FROM_NEW) -#define OPERATOR_NEW_BODY_ARRAY \ - GET_STACK_TRACE_MALLOC; \ - void *res = asan_memalign(0, size, &stack, FROM_NEW_BR); \ - if (UNLIKELY(!res)) \ - ReportOutOfMemory(size, &stack); \ + return asan_new(size, &stack) +#define OPERATOR_NEW_BODY_ARRAY \ + GET_STACK_TRACE_MALLOC; \ + void *res = asan_new_array(size, &stack); \ + if (UNLIKELY(!res)) \ + ReportOutOfMemory(size, &stack); \ return res #define OPERATOR_NEW_BODY_ARRAY_NOTHROW \ GET_STACK_TRACE_MALLOC; \ - return asan_memalign(0, size, &stack, FROM_NEW_BR) -#define OPERATOR_NEW_BODY_ALIGN \ - GET_STACK_TRACE_MALLOC; \ - void *res = asan_memalign((uptr)align, size, &stack, FROM_NEW); \ - if (UNLIKELY(!res)) \ - ReportOutOfMemory(size, &stack); \ + return asan_new_array(size, &stack) +#define OPERATOR_NEW_BODY_ALIGN \ + GET_STACK_TRACE_MALLOC; \ + void *res = asan_new_aligned(size, static_cast(align), &stack); \ + if (UNLIKELY(!res)) \ + ReportOutOfMemory(size, &stack); \ return res #define OPERATOR_NEW_BODY_ALIGN_NOTHROW \ GET_STACK_TRACE_MALLOC; \ - return asan_memalign((uptr)align, size, &stack, FROM_NEW) -#define OPERATOR_NEW_BODY_ALIGN_ARRAY \ - GET_STACK_TRACE_MALLOC; \ - void *res = asan_memalign((uptr)align, size, &stack, FROM_NEW_BR); \ - if (UNLIKELY(!res)) \ - ReportOutOfMemory(size, &stack); \ + return asan_new_aligned(size, static_cast(align), &stack) +#define OPERATOR_NEW_BODY_ALIGN_ARRAY \ + GET_STACK_TRACE_MALLOC; \ + void *res = asan_new_array_aligned(size, static_cast(align), &stack); \ + if (UNLIKELY(!res)) \ + ReportOutOfMemory(size, &stack); \ return res #define OPERATOR_NEW_BODY_ALIGN_ARRAY_NOTHROW \ GET_STACK_TRACE_MALLOC; \ - return asan_memalign((uptr)align, size, &stack, FROM_NEW_BR) + return asan_new_array_aligned(size, static_cast(align), &stack) // On OS X it's not enough to just provide our own 'operator new' and // 'operator delete' implementations, because they're going to be in the @@ -149,28 +149,28 @@ INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) { #define OPERATOR_DELETE_BODY \ GET_STACK_TRACE_FREE; \ - asan_delete(ptr, 0, 0, &stack, FROM_NEW) + asan_delete(ptr, &stack) #define OPERATOR_DELETE_BODY_ARRAY \ GET_STACK_TRACE_FREE; \ - asan_delete(ptr, 0, 0, &stack, FROM_NEW_BR) + asan_delete_array(ptr, &stack) #define OPERATOR_DELETE_BODY_ALIGN \ GET_STACK_TRACE_FREE; \ - asan_delete(ptr, 0, static_cast(align), &stack, FROM_NEW) + asan_delete_aligned(ptr, static_cast(align), &stack) #define OPERATOR_DELETE_BODY_ALIGN_ARRAY \ GET_STACK_TRACE_FREE; \ - asan_delete(ptr, 0, static_cast(align), &stack, FROM_NEW_BR) + asan_delete_array_aligned(ptr, static_cast(align), &stack) #define OPERATOR_DELETE_BODY_SIZE \ GET_STACK_TRACE_FREE; \ - asan_delete(ptr, size, 0, &stack, FROM_NEW) + asan_delete_sized(ptr, size, &stack) #define OPERATOR_DELETE_BODY_SIZE_ARRAY \ GET_STACK_TRACE_FREE; \ - asan_delete(ptr, size, 0, &stack, FROM_NEW_BR) + asan_delete_array_sized(ptr, size, &stack) #define OPERATOR_DELETE_BODY_SIZE_ALIGN \ GET_STACK_TRACE_FREE; \ - asan_delete(ptr, size, static_cast(align), &stack, FROM_NEW) + asan_delete_sized_aligned(ptr, size, static_cast(align), &stack) #define OPERATOR_DELETE_BODY_SIZE_ALIGN_ARRAY \ GET_STACK_TRACE_FREE; \ - asan_delete(ptr, size, static_cast(align), &stack, FROM_NEW_BR) + asan_delete_array_sized_aligned(ptr, size, static_cast(align), &stack) #if !SANITIZER_APPLE CXX_OPERATOR_ATTRIBUTE diff --git a/compiler-rt/lib/asan/tests/asan_noinst_test.cpp b/compiler-rt/lib/asan/tests/asan_noinst_test.cpp index f485404758b54..401219ac3628c 100644 --- a/compiler-rt/lib/asan/tests/asan_noinst_test.cpp +++ b/compiler-rt/lib/asan/tests/asan_noinst_test.cpp @@ -71,7 +71,7 @@ static void *MallocStress(void *NumOfItrPtr) { void *ptr = vec[idx]; vec[idx] = vec.back(); vec.pop_back(); - __asan::asan_free(ptr, &stack1, __asan::FROM_MALLOC); + __asan::asan_free(ptr, &stack1); } else { size_t size = my_rand_r(&seed) % 1000 + 1; switch ((my_rand_r(&seed) % 128)) { @@ -80,8 +80,7 @@ static void *MallocStress(void *NumOfItrPtr) { case 2: size += 4096; break; } size_t alignment = 1 << (my_rand_r(&seed) % 10 + 1); - char *ptr = (char *)__asan::asan_memalign(alignment, size, &stack2, - __asan::FROM_MALLOC); + char *ptr = (char *)__asan::asan_memalign(alignment, size, &stack2); EXPECT_EQ(size, __asan::asan_malloc_usable_size(ptr, 0, 0)); vec.push_back(ptr); ptr[0] = 0; @@ -89,8 +88,7 @@ static void *MallocStress(void *NumOfItrPtr) { ptr[size/2] = 0; } } - for (size_t i = 0; i < vec.size(); i++) - __asan::asan_free(vec[i], &stack3, __asan::FROM_MALLOC); + for (size_t i = 0; i < vec.size(); i++) __asan::asan_free(vec[i], &stack3); return nullptr; } @@ -143,12 +141,12 @@ TEST(AddressSanitizer, QuarantineTest) { const int size = 1024; void *p = __asan::asan_malloc(size, &stack); - __asan::asan_free(p, &stack, __asan::FROM_MALLOC); + __asan::asan_free(p, &stack); size_t i; size_t max_i = 1 << 30; for (i = 0; i < max_i; i++) { void *p1 = __asan::asan_malloc(size, &stack); - __asan::asan_free(p1, &stack, __asan::FROM_MALLOC); + __asan::asan_free(p1, &stack); if (p1 == p) break; } EXPECT_GE(i, 10000U); @@ -165,7 +163,7 @@ void *ThreadedQuarantineTestWorker(void *unused) { for (size_t i = 0; i < 1000; i++) { void *p = __asan::asan_malloc(1 + (my_rand_r(&seed) % 4000), &stack); - __asan::asan_free(p, &stack, __asan::FROM_MALLOC); + __asan::asan_free(p, &stack); } return NULL; } @@ -204,7 +202,7 @@ void *ThreadedOneSizeMallocStress(void *unused) { p[i] = __asan::asan_malloc(32, &stack); } for (size_t i = 0; i < kNumMallocs; i++) { - __asan::asan_free(p[i], &stack, __asan::FROM_MALLOC); + __asan::asan_free(p[i], &stack); } } return NULL; @@ -260,7 +258,7 @@ static void TestLoadStoreCallbacks(CB cb[2][5]) { } } } - __asan::asan_free(ptr, &stack, __asan::FROM_MALLOC); + __asan::asan_free(ptr, &stack); } __asan_test_only_reported_buggy_pointer = 0; } diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt index 3ab92403d4168..eb2e7664152b8 100644 --- a/compiler-rt/lib/builtins/CMakeLists.txt +++ b/compiler-rt/lib/builtins/CMakeLists.txt @@ -591,10 +591,16 @@ set(aarch64_SOURCES ${GENERIC_TF_SOURCES} ${GENERIC_SOURCES} cpu_model/aarch64.c - aarch64/emupac.cpp aarch64/fp_mode.c ) +# Append sources specific to AArch64 targets that aren't supported by MSVC. +if(NOT MSVC) + list(APPEND aarch64_SOURCES + aarch64/emupac.cpp + ) +endif() + set(COMPILER_RT_AARCH64_FMV_USES_GLOBAL_CONSTRUCTOR NOT(FUCHSIA OR APPLE)) if (COMPILER_RT_HAS_AARCH64_SME) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h index a2b6c37d5450c..00e237a24fc91 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -102,6 +102,8 @@ const unsigned struct_kernel_stat_sz = SANITIZER_ANDROID ? FIRST_32_SECOND_64(104, 128) # if defined(_ABIN32) && _MIPS_SIM == _ABIN32 : FIRST_32_SECOND_64(176, 216); +# elif SANITIZER_MUSL + : FIRST_32_SECOND_64(160, 208); # else : FIRST_32_SECOND_64(160, 216); # endif @@ -476,6 +478,30 @@ struct __sanitizer_cmsghdr { int cmsg_level; int cmsg_type; }; +# elif SANITIZER_MUSL +struct __sanitizer_msghdr { + void *msg_name; + unsigned msg_namelen; + struct __sanitizer_iovec *msg_iov; + int msg_iovlen; +# if SANITIZER_WORDSIZE == 64 + int __pad1; +# endif + void *msg_control; + unsigned msg_controllen; +# if SANITIZER_WORDSIZE == 64 + int __pad2; +# endif + int msg_flags; +}; +struct __sanitizer_cmsghdr { + unsigned cmsg_len; +# if SANITIZER_WORDSIZE == 64 + int __pad1; +# endif + int cmsg_level; + int cmsg_type; +}; # else // In POSIX, int msg_iovlen; socklen_t msg_controllen; socklen_t cmsg_len; but // many implementations don't conform to the standard. diff --git a/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh b/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh index 4d435976d3a10..567402ee85e96 100755 --- a/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh +++ b/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh @@ -87,7 +87,7 @@ AR="${AR}" CC="${CC}" CFLAGS="$FLAGS -Wno-deprecated-non-prototype" RANLIB=/bin/ make -j libz.a # Build and install libcxxabi and libcxx. -if [[ ! -f ${LLVM_BUILD}/build.ninja ]]; then +if [[ ! -f ${LIBCXX_BUILD}/build.ninja ]]; then rm -rf "${LIBCXX_BUILD}" "${LIBCXX_INSTALL}" mkdir -p ${LIBCXX_BUILD} ${LIBCXX_INSTALL} cd ${LIBCXX_BUILD} @@ -120,7 +120,7 @@ ninja cxx cxxabi && ninja install-cxx install-cxxabi FLAGS="${FLAGS} -fno-rtti -fno-exceptions" LLVM_CFLAGS="${FLAGS} -Wno-global-constructors" -LLVM_CXXFLAGS="${LLVM_CFLAGS} -nostdinc++ -I${ZLIB_BUILD} -isystem ${LIBCXX_INSTALL}/include -isystem ${LIBCXX_INSTALL}/include/c++/v1" +LLVM_CXXFLAGS="-isystem ${LIBCXX_INSTALL}/include -isystem ${LIBCXX_INSTALL}/include/c++/v1 ${LLVM_CFLAGS} -nostdinc++ -I${ZLIB_BUILD}" # Build LLVM. if [[ ! -f ${LLVM_BUILD}/build.ninja ]]; then diff --git a/compiler-rt/lib/scudo/standalone/tests/common_test.cpp b/compiler-rt/lib/scudo/standalone/tests/common_test.cpp index e6ddbb00b843c..71f810e9d9724 100644 --- a/compiler-rt/lib/scudo/standalone/tests/common_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/common_test.cpp @@ -11,44 +11,60 @@ #include "common.h" #include "mem_map.h" + +#include +#include +#include + #include -#include +#include namespace scudo { -static uptr getResidentMemorySize() { - if (!SCUDO_LINUX) - UNREACHABLE("Not implemented!"); - uptr Size; - uptr Resident; - std::ifstream IFS("/proc/self/statm"); - IFS >> Size; - IFS >> Resident; - return Resident * getPageSizeCached(); +static void getResidentPages(void *BaseAddress, size_t TotalPages, + size_t *ResidentPages) { + std::vector Pages(TotalPages, 0); + ASSERT_EQ( + 0, mincore(BaseAddress, TotalPages * getPageSizeCached(), Pages.data())) + << strerror(errno); + *ResidentPages = 0; + for (unsigned char Value : Pages) { + if (Value & 1) { + ++*ResidentPages; + } + } } -// Fuchsia needs getResidentMemorySize implementation. +// Fuchsia needs getResidentPages implementation. TEST(ScudoCommonTest, SKIP_ON_FUCHSIA(ResidentMemorySize)) { - uptr OnStart = getResidentMemorySize(); - EXPECT_GT(OnStart, 0UL); - - const uptr Size = 1ull << 30; - const uptr Threshold = Size >> 3; + // Make sure to have the size of the map on a page boundary. + const uptr PageSize = getPageSizeCached(); + const size_t NumPages = 1000; + const uptr SizeBytes = NumPages * PageSize; MemMapT MemMap; - ASSERT_TRUE(MemMap.map(/*Addr=*/0U, Size, "ResidentMemorySize")); + ASSERT_TRUE(MemMap.map(/*Addr=*/0U, SizeBytes, "ResidentMemorySize")); ASSERT_NE(MemMap.getBase(), 0U); - void *P = reinterpret_cast(MemMap.getBase()); - EXPECT_LT(getResidentMemorySize(), OnStart + Threshold); - - memset(P, 1, Size); - EXPECT_GT(getResidentMemorySize(), OnStart + Size - Threshold); - - MemMap.releasePagesToOS(MemMap.getBase(), Size); - EXPECT_LT(getResidentMemorySize(), OnStart + Threshold); - memset(P, 1, Size); - EXPECT_GT(getResidentMemorySize(), OnStart + Size - Threshold); + void *P = reinterpret_cast(MemMap.getBase()); + size_t ResidentPages; + getResidentPages(P, NumPages, &ResidentPages); + EXPECT_EQ(0U, ResidentPages); + + // Make the entire map resident. + memset(P, 1, SizeBytes); + getResidentPages(P, NumPages, &ResidentPages); + EXPECT_EQ(NumPages, ResidentPages); + + // Should release the memory to the kernel immediately. + MemMap.releasePagesToOS(MemMap.getBase(), SizeBytes); + getResidentPages(P, NumPages, &ResidentPages); + EXPECT_EQ(0U, ResidentPages); + + // Make the entire map resident again. + memset(P, 1, SizeBytes); + getResidentPages(P, NumPages, &ResidentPages); + EXPECT_EQ(NumPages, ResidentPages); MemMap.unmap(); } diff --git a/compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp b/compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp index 05065444a70c5..612317b3c3293 100644 --- a/compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp @@ -183,7 +183,8 @@ TEST_F(ScudoWrappersCDeathTest, Malloc) { // process doing free(P) is not a double free. EXPECT_DEATH( { - void *Ptr = malloc(Size); + // Note: volatile here prevents the calls from being optimized out. + void *volatile Ptr = malloc(Size); free(Ptr); free(Ptr); }, diff --git a/compiler-rt/lib/tysan/lit.cfg b/compiler-rt/lib/tysan/lit.cfg index e3ef6c9c97147..c906c03cc3fb2 100644 --- a/compiler-rt/lib/tysan/lit.cfg +++ b/compiler-rt/lib/tysan/lit.cfg @@ -27,7 +27,7 @@ config.substitutions.append( ("%clangxx_tysan ", build_invocation(clang_tysan_cx config.suffixes = ['.c', '.cc', '.cpp'] # TypeSanitizer tests are currently supported on Linux only. -if config.host_os not in ['Linux']: +if config.target_os not in ['Linux']: config.unsupported = True if config.target_arch != 'aarch64': diff --git a/compiler-rt/test/asan/TestCases/Darwin/lit.local.cfg.py b/compiler-rt/test/asan/TestCases/Darwin/lit.local.cfg.py index 520a963d01198..af82d30cf4de9 100644 --- a/compiler-rt/test/asan/TestCases/Darwin/lit.local.cfg.py +++ b/compiler-rt/test/asan/TestCases/Darwin/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ["Darwin"]: +if root.target_os not in ["Darwin"]: config.unsupported = True diff --git a/compiler-rt/test/asan/TestCases/Linux/lit.local.cfg.py b/compiler-rt/test/asan/TestCases/Linux/lit.local.cfg.py index 603ca0365068f..3ea05fa044356 100644 --- a/compiler-rt/test/asan/TestCases/Linux/lit.local.cfg.py +++ b/compiler-rt/test/asan/TestCases/Linux/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ["Linux"]: +if root.target_os not in ["Linux"]: config.unsupported = True diff --git a/compiler-rt/test/asan/TestCases/Posix/lit.local.cfg.py b/compiler-rt/test/asan/TestCases/Posix/lit.local.cfg.py index 63240c3962565..c43790b98f38a 100644 --- a/compiler-rt/test/asan/TestCases/Posix/lit.local.cfg.py +++ b/compiler-rt/test/asan/TestCases/Posix/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os in ["Windows"]: +if root.target_os in ["Windows"]: config.unsupported = True diff --git a/compiler-rt/test/asan/TestCases/Windows/lit.local.cfg.py b/compiler-rt/test/asan/TestCases/Windows/lit.local.cfg.py index 57c0979e60962..b622e072bcbfb 100644 --- a/compiler-rt/test/asan/TestCases/Windows/lit.local.cfg.py +++ b/compiler-rt/test/asan/TestCases/Windows/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ["Windows"]: +if root.target_os not in ["Windows"]: config.unsupported = True diff --git a/compiler-rt/test/asan/lit.cfg.py b/compiler-rt/test/asan/lit.cfg.py index 3da073332c458..96201e679b0a3 100644 --- a/compiler-rt/test/asan/lit.cfg.py +++ b/compiler-rt/test/asan/lit.cfg.py @@ -28,7 +28,7 @@ def get_required_attr(config, attr_name): # tests to prevent regressions. # Currently, detect_leaks for asan tests only work on Intel MacOS. if ( - config.host_os == "Darwin" + config.target_os == "Darwin" and config.apple_platform == "osx" and config.target_arch == "x86_64" ): @@ -45,7 +45,7 @@ def get_required_attr(config, attr_name): # Setup source root. config.test_source_root = os.path.dirname(__file__) -if config.host_os not in ["FreeBSD", "NetBSD"]: +if config.target_os not in ["FreeBSD", "NetBSD"]: libdl_flag = "-ldl" else: libdl_flag = "" @@ -125,17 +125,17 @@ def build_invocation(compile_flags, with_lto=False): ("%clangxx_asan_lto ", build_invocation(clang_asan_cxxflags, True)) ) if config.asan_dynamic: - if config.host_os in ["Linux", "FreeBSD", "NetBSD", "SunOS"]: + if config.target_os in ["Linux", "FreeBSD", "NetBSD", "SunOS"]: shared_libasan_path = os.path.join( config.compiler_rt_libdir, "libclang_rt.asan{}.so".format(config.target_suffix), ) - elif config.host_os == "Darwin": + elif config.target_os == "Darwin": shared_libasan_path = os.path.join( config.compiler_rt_libdir, "libclang_rt.asan_{}_dynamic.dylib".format(config.apple_platform), ) - elif config.host_os == "Windows": + elif config.target_os == "Windows": shared_libasan_path = os.path.join( config.compiler_rt_libdir, "clang_rt.asan_dynamic-{}.lib".format(config.target_suffix), @@ -274,16 +274,16 @@ def build_invocation(compile_flags, with_lto=False): and (config.target_arch in ["x86_64", "i386", "i686", "aarch64"]) ) leak_detection_linux = ( - (config.host_os == "Linux") + (config.target_os == "Linux") and (not config.android) and (config.target_arch in ["x86_64", "i386", "riscv64", "loongarch64"]) ) leak_detection_mac = ( - (config.host_os == "Darwin") + (config.target_os == "Darwin") and (config.apple_platform == "osx") and (config.target_arch == "x86_64") ) -leak_detection_netbsd = (config.host_os == "NetBSD") and ( +leak_detection_netbsd = (config.target_os == "NetBSD") and ( config.target_arch in ["x86_64", "i386"] ) if ( @@ -296,7 +296,7 @@ def build_invocation(compile_flags, with_lto=False): # Add the RT libdir to PATH directly so that we can successfully run the gtest # binary to list its tests. -if config.host_os == "Windows": +if config.target_os == "Windows": os.environ["PATH"] = os.path.pathsep.join( [config.compiler_rt_libdir, os.environ.get("PATH", "")] ) @@ -310,10 +310,10 @@ def build_invocation(compile_flags, with_lto=False): # Default test suffixes. config.suffixes = [".c", ".cpp"] -if config.host_os == "Darwin": +if config.target_os == "Darwin": config.suffixes.append(".mm") -if config.host_os == "Windows": +if config.target_os == "Windows": config.substitutions.append(("%fPIC", "")) config.substitutions.append(("%fPIE", "")) config.substitutions.append(("%pie", "")) @@ -323,11 +323,11 @@ def build_invocation(compile_flags, with_lto=False): config.substitutions.append(("%pie", "-pie")) # Only run the tests on supported OSs. -if config.host_os not in ["Linux", "Darwin", "FreeBSD", "SunOS", "Windows", "NetBSD"]: +if config.target_os not in ["Linux", "Darwin", "FreeBSD", "SunOS", "Windows", "NetBSD"]: config.unsupported = True if not config.parallelism_group: config.parallelism_group = "shadow-memory" -if config.host_os == "NetBSD": +if config.target_os == "NetBSD": config.substitutions.insert(0, ("%run", config.netbsd_noaslr_prefix)) diff --git a/compiler-rt/test/asan_abi/lit.cfg.py b/compiler-rt/test/asan_abi/lit.cfg.py index 5bc1881ed9c32..dd99a5373e7b6 100644 --- a/compiler-rt/test/asan_abi/lit.cfg.py +++ b/compiler-rt/test/asan_abi/lit.cfg.py @@ -68,7 +68,7 @@ def build_invocation(compile_flags): config.suffixes = ['.c', '.cpp'] -if config.host_os == 'Darwin': +if config.target_os == 'Darwin': config.suffixes.append('.mm') else: config.unsupported = True diff --git a/compiler-rt/test/builtins/TestCases/Darwin/lit.local.cfg.py b/compiler-rt/test/builtins/TestCases/Darwin/lit.local.cfg.py index 520a963d01198..af82d30cf4de9 100644 --- a/compiler-rt/test/builtins/TestCases/Darwin/lit.local.cfg.py +++ b/compiler-rt/test/builtins/TestCases/Darwin/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ["Darwin"]: +if root.target_os not in ["Darwin"]: config.unsupported = True diff --git a/compiler-rt/test/builtins/Unit/lit.cfg.py b/compiler-rt/test/builtins/Unit/lit.cfg.py index c030f89c66e42..59da054848f3c 100644 --- a/compiler-rt/test/builtins/Unit/lit.cfg.py +++ b/compiler-rt/test/builtins/Unit/lit.cfg.py @@ -80,10 +80,10 @@ def get_libgcc_file_name(): config.compiler_rt_libdir, "clang_rt.builtins%s.lib " % config.target_suffix ) config.substitutions.append(("%librt ", base_lib)) -elif config.host_os == "Darwin": +elif config.target_os == "Darwin": base_lib = os.path.join(config.compiler_rt_libdir, "libclang_rt.osx.a ") config.substitutions.append(("%librt ", base_lib + " -lSystem ")) -elif config.host_os == "Windows": +elif config.target_os == "Windows": base_lib = os.path.join( config.compiler_rt_libdir, "libclang_rt.builtins%s.a" % config.target_suffix ) @@ -104,7 +104,7 @@ def get_libgcc_file_name(): if sys.platform in ["win32"] and execute_external: # Don't pass dosish path separator to msys bash.exe. base_lib = base_lib.replace("\\", "/") - if config.host_os == "Haiku": + if config.target_os == "Haiku": config.substitutions.append(("%librt ", base_lib + " -lroot ")) else: config.substitutions.append(("%librt ", base_lib + " -lc -lm ")) diff --git a/compiler-rt/test/builtins/lit.cfg.py b/compiler-rt/test/builtins/lit.cfg.py index 9300488c8428d..6491f4735b9e6 100644 --- a/compiler-rt/test/builtins/lit.cfg.py +++ b/compiler-rt/test/builtins/lit.cfg.py @@ -21,7 +21,7 @@ ("%clang ", " " + config.clang + " " + " ".join(extra_flags) + " ") ) -if config.host_os == "Darwin": +if config.target_os == "Darwin": config.substitutions.append( ("%macos_version_major", str(config.darwin_osx_version[0])) ) diff --git a/compiler-rt/test/cfi/cross-dso/lit.local.cfg.py b/compiler-rt/test/cfi/cross-dso/lit.local.cfg.py index dceb7cde7218b..2778d8c995fd1 100644 --- a/compiler-rt/test/cfi/cross-dso/lit.local.cfg.py +++ b/compiler-rt/test/cfi/cross-dso/lit.local.cfg.py @@ -6,7 +6,7 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ["Linux", "FreeBSD", "NetBSD"]: +if root.target_os not in ["Linux", "FreeBSD", "NetBSD"]: config.unsupported = True # Android O (API level 26) has support for cross-dso cfi in libdl.so. diff --git a/compiler-rt/test/ctx_profile/lit.cfg.py b/compiler-rt/test/ctx_profile/lit.cfg.py index 74d9bfd11ae28..75367d95a47bd 100644 --- a/compiler-rt/test/ctx_profile/lit.cfg.py +++ b/compiler-rt/test/ctx_profile/lit.cfg.py @@ -7,7 +7,7 @@ import lit.formats # Only run the tests on supported OSs. -if config.host_os not in ["Linux"]: +if config.target_os not in ["Linux"]: config.unsupported = True diff --git a/compiler-rt/test/dfsan/lit.cfg.py b/compiler-rt/test/dfsan/lit.cfg.py index e947c51f99a5b..b26ff3e367942 100644 --- a/compiler-rt/test/dfsan/lit.cfg.py +++ b/compiler-rt/test/dfsan/lit.cfg.py @@ -25,5 +25,5 @@ def build_invocation(compile_flags): config.suffixes = [".c", ".cpp"] # DataFlowSanitizer tests are currently supported on Linux only. -if not (config.host_os in ["Linux"] and config.target_arch in ["aarch64", "x86_64", "loongarch64"]): +if not (config.target_os in ["Linux"] and config.target_arch in ["aarch64", "x86_64", "loongarch64"]): config.unsupported = True diff --git a/compiler-rt/test/fuzzer/lit.cfg.py b/compiler-rt/test/fuzzer/lit.cfg.py index 75d4cf2e4c529..1689f53d0b021 100644 --- a/compiler-rt/test/fuzzer/lit.cfg.py +++ b/compiler-rt/test/fuzzer/lit.cfg.py @@ -149,5 +149,5 @@ def generate_compiler_cmd(is_cpp=True, fuzzer_enabled=True, msan_enabled=False): if not config.parallelism_group: config.parallelism_group = "shadow-memory" -if config.host_os == "NetBSD": +if config.target_os == "NetBSD": config.substitutions.insert(0, ("%run", config.netbsd_noaslr_prefix)) diff --git a/compiler-rt/test/gwp_asan/lit.cfg.py b/compiler-rt/test/gwp_asan/lit.cfg.py index 7f68682162e3f..1592cf400023e 100644 --- a/compiler-rt/test/gwp_asan/lit.cfg.py +++ b/compiler-rt/test/gwp_asan/lit.cfg.py @@ -67,5 +67,5 @@ def build_invocation(compile_flags): ) # GWP-ASan tests are currently supported on Linux only. -if config.host_os not in ["Linux"]: +if config.target_os not in ["Linux"]: config.unsupported = True diff --git a/compiler-rt/test/hwasan/TestCases/Linux/lit.local.cfg.py b/compiler-rt/test/hwasan/TestCases/Linux/lit.local.cfg.py index 603ca0365068f..3ea05fa044356 100644 --- a/compiler-rt/test/hwasan/TestCases/Linux/lit.local.cfg.py +++ b/compiler-rt/test/hwasan/TestCases/Linux/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ["Linux"]: +if root.target_os not in ["Linux"]: config.unsupported = True diff --git a/compiler-rt/test/hwasan/TestCases/Posix/lit.local.cfg.py b/compiler-rt/test/hwasan/TestCases/Posix/lit.local.cfg.py index 63240c3962565..c43790b98f38a 100644 --- a/compiler-rt/test/hwasan/TestCases/Posix/lit.local.cfg.py +++ b/compiler-rt/test/hwasan/TestCases/Posix/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os in ["Windows"]: +if root.target_os in ["Windows"]: config.unsupported = True diff --git a/compiler-rt/test/hwasan/lit.cfg.py b/compiler-rt/test/hwasan/lit.cfg.py index bbf23e683240a..3a1c8e1466aea 100644 --- a/compiler-rt/test/hwasan/lit.cfg.py +++ b/compiler-rt/test/hwasan/lit.cfg.py @@ -86,5 +86,5 @@ def build_invocation(compile_flags): # Default test suffixes. config.suffixes = [".c", ".cpp"] -if config.host_os not in ["Linux", "Android"] or not config.has_lld: +if config.target_os not in ["Linux", "Android"] or not config.has_lld: config.unsupported = True diff --git a/compiler-rt/test/lit.common.cfg.py b/compiler-rt/test/lit.common.cfg.py index f5576ce0e013d..8328b407dcc36 100644 --- a/compiler-rt/test/lit.common.cfg.py +++ b/compiler-rt/test/lit.common.cfg.py @@ -66,7 +66,7 @@ def find_compiler_libdir(): # Fall back for older AppleClang that doesn't support `-print-runtime-dir` # Note `-print-file-name=` was broken for Apple # platforms so we can't use that approach here (see https://reviews.llvm.org/D101682). - if config.host_os == "Darwin": + if config.target_os == "Darwin": lib_dir, _ = get_path_from_clang(["-print-file-name=lib"], allow_failure=False) runtime_dir = os.path.join(lib_dir, "darwin") if not os.path.exists(runtime_dir): @@ -312,7 +312,7 @@ def push_dynamic_library_lookup_path(config, new_path): if platform.system() == "Windows" and target_is_msvc: config.environment["LIB"] = os.environ["LIB"] -config.available_features.add(config.host_os.lower()) +config.available_features.add(config.target_os.lower()) if config.target_triple.startswith("ppc") or config.target_triple.startswith("powerpc"): config.available_features.add("ppc") @@ -344,7 +344,7 @@ def push_dynamic_library_lookup_path(config, new_path): ) ) -if config.host_os == "NetBSD": +if config.target_os == "NetBSD": nb_commands_dir = os.path.join( config.compiler_rt_src_root, "test", "sanitizer_common", "netbsd_commands" ) @@ -395,7 +395,7 @@ def get_ios_commands_dir(): if sanitizer not in config.environment: config.environment[sanitizer] = symbolizer_path -env_utility = "/opt/freeware/bin/env" if config.host_os == "AIX" else "env" +env_utility = "/opt/freeware/bin/env" if config.target_os == "AIX" else "env" env_unset_command = " ".join(f"-u {var}" for var in tool_symbolizer_path_list) config.substitutions.append( ("%env_unset_tool_symbolizer_path", f"{env_utility} {env_unset_command}") @@ -410,7 +410,7 @@ def get_ios_commands_dir(): lit_config.warning("%device_rm is not implemented") config.substitutions.append(("%device_rm", "echo ")) config.compile_wrapper = "" -elif config.host_os == "Darwin" and config.apple_platform != "osx": +elif config.target_os == "Darwin" and config.apple_platform != "osx": # Darwin tests can be targetting macOS, a device or a simulator. All devices # are declared as "ios", even for iOS derivatives (tvOS, watchOS). Similarly, # all simulators are "iossim". See the table below. @@ -498,7 +498,7 @@ def get_ios_commands_dir(): config.compile_wrapper = "" # Define CHECK-%os to check for OS-dependent output. -config.substitutions.append(("CHECK-%os", ("CHECK-" + config.host_os))) +config.substitutions.append(("CHECK-%os", ("CHECK-" + config.target_os))) # Define %arch to check for architecture-dependent output. config.substitutions.append(("%arch", (config.host_arch))) @@ -519,7 +519,7 @@ def get_ios_commands_dir(): config.available_features.add(target_arch + "-target-arch") if target_arch in ["x86_64", "i386"]: config.available_features.add("x86-target-arch") - config.available_features.add(target_arch + "-" + config.host_os.lower()) + config.available_features.add(target_arch + "-" + config.target_os.lower()) compiler_rt_debug = getattr(config, "compiler_rt_debug", False) if not compiler_rt_debug: @@ -565,7 +565,7 @@ def get_ios_commands_dir(): ("%darwin_min_target_with_tls_support", "%min_macos_deployment_target=10.12") ) -if config.host_os == "Darwin": +if config.target_os == "Darwin": osx_version = (10, 0, 0) try: osx_version = subprocess.check_output( @@ -602,12 +602,12 @@ def get_ios_commands_dir(): def get_macos_aligned_version(macos_vers): platform = config.apple_platform - if platform == "osx": + macos_major, macos_minor = macos_vers + + if platform == "osx" or macos_major >= 26: return macos_vers - macos_major, macos_minor = macos_vers assert macos_major >= 10 - if macos_major == 10: # macOS 10.x major = macos_minor minor = 0 @@ -708,7 +708,7 @@ def get_macos_aligned_version(macos_vers): config.substitutions.append(("%push_to_device", "echo ")) config.substitutions.append(("%adb_shell", "echo ")) -if config.host_os == "Linux": +if config.target_os == "Linux": def add_glibc_versions(ver_string): if config.android: return @@ -806,10 +806,10 @@ def is_windows_lto_supported(): return os.path.exists(os.path.join(config.llvm_tools_dir, "lld-link.exe")) -if config.host_os == "Darwin" and is_darwin_lto_supported(): +if config.target_os == "Darwin" and is_darwin_lto_supported(): config.lto_supported = True config.lto_flags = ["-Wl,-lto_library," + liblto_path()] -elif config.host_os in ["Linux", "FreeBSD", "NetBSD"]: +elif config.target_os in ["Linux", "FreeBSD", "NetBSD"]: config.lto_supported = False if config.use_lld and is_lld_lto_supported(): config.lto_supported = True @@ -822,7 +822,7 @@ def is_windows_lto_supported(): config.lto_flags = ["-fuse-ld=lld"] else: config.lto_flags = ["-fuse-ld=gold"] -elif config.host_os == "Windows" and is_windows_lto_supported(): +elif config.target_os == "Windows" and is_windows_lto_supported(): config.lto_supported = True config.lto_flags = ["-fuse-ld=lld"] else: @@ -871,7 +871,7 @@ def is_windows_lto_supported(): # Note that substitutions with numbers have to be defined first to avoid # being subsumed by substitutions with smaller postfix. for postfix in ["2", "1", ""]: - if config.host_os == "Darwin": + if config.target_os == "Darwin": config.substitutions.append( ( "%ld_flags_rpath_exe" + postfix, @@ -884,7 +884,7 @@ def is_windows_lto_supported(): "-install_name @rpath/`basename %dynamiclib{}`".format(postfix), ) ) - elif config.host_os in ("FreeBSD", "NetBSD", "OpenBSD"): + elif config.target_os in ("FreeBSD", "NetBSD", "OpenBSD"): config.substitutions.append( ( "%ld_flags_rpath_exe" + postfix, @@ -893,7 +893,7 @@ def is_windows_lto_supported(): ) ) config.substitutions.append(("%ld_flags_rpath_so" + postfix, "")) - elif config.host_os == "Linux": + elif config.target_os == "Linux": config.substitutions.append( ( "%ld_flags_rpath_exe" + postfix, @@ -901,7 +901,7 @@ def is_windows_lto_supported(): ) ) config.substitutions.append(("%ld_flags_rpath_so" + postfix, "")) - elif config.host_os == "SunOS": + elif config.target_os == "SunOS": config.substitutions.append( ( "%ld_flags_rpath_exe" + postfix, @@ -923,7 +923,7 @@ def is_windows_lto_supported(): config.substitutions.append(("%xdynamiclib_namespec", "%basename_t.dynamic")) config.default_sanitizer_opts = [] -if config.host_os == "Darwin": +if config.target_os == "Darwin": # On Darwin, we default to `abort_on_error=1`, which would make tests run # much slower. Let's override this and run lit tests with 'abort_on_error=0'. config.default_sanitizer_opts += ["abort_on_error=0"] @@ -983,7 +983,7 @@ def is_windows_lto_supported(): elif config.use_lld and (not config.has_lld): config.unsupported = True -if config.host_os == "Darwin": +if config.target_os == "Darwin": if getattr(config, "darwin_linker_version", None): extra_cflags += ["-mlinker-version=" + config.darwin_linker_version] @@ -998,7 +998,7 @@ def is_windows_lto_supported(): ) config.target_cflags = " " + " ".join(target_cflags + extra_cflags) + " " -if config.host_os == "Darwin": +if config.target_os == "Darwin": config.substitutions.append( ( "%get_pid_from_output", diff --git a/compiler-rt/test/lit.common.configured.in b/compiler-rt/test/lit.common.configured.in index 04d1a4df5a54f..2b4b72bc895c5 100644 --- a/compiler-rt/test/lit.common.configured.in +++ b/compiler-rt/test/lit.common.configured.in @@ -10,7 +10,7 @@ set_default("target_triple", "@COMPILER_RT_DEFAULT_TARGET_TRIPLE@") set_default("target_cflags", "@COMPILER_RT_TEST_COMPILER_CFLAGS@") set_default("host_arch", "@HOST_ARCH@") set_default("target_arch", "@COMPILER_RT_DEFAULT_TARGET_ARCH@") -set_default("host_os", "@HOST_OS@") +set_default("target_os", "@HOST_OS@") set_default("llvm_build_mode", "@LLVM_BUILD_MODE@") set_default("llvm_src_root", "@LLVM_MAIN_SRC_DIR@") set_default("llvm_obj_root", "@LLVM_BINARY_DIR@") diff --git a/compiler-rt/test/lsan/TestCases/Darwin/lit.local.cfg.py b/compiler-rt/test/lsan/TestCases/Darwin/lit.local.cfg.py index 520a963d01198..af82d30cf4de9 100644 --- a/compiler-rt/test/lsan/TestCases/Darwin/lit.local.cfg.py +++ b/compiler-rt/test/lsan/TestCases/Darwin/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ["Darwin"]: +if root.target_os not in ["Darwin"]: config.unsupported = True diff --git a/compiler-rt/test/lsan/TestCases/Linux/lit.local.cfg.py b/compiler-rt/test/lsan/TestCases/Linux/lit.local.cfg.py index 603ca0365068f..3ea05fa044356 100644 --- a/compiler-rt/test/lsan/TestCases/Linux/lit.local.cfg.py +++ b/compiler-rt/test/lsan/TestCases/Linux/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ["Linux"]: +if root.target_os not in ["Linux"]: config.unsupported = True diff --git a/compiler-rt/test/lsan/TestCases/Posix/lit.local.cfg.py b/compiler-rt/test/lsan/TestCases/Posix/lit.local.cfg.py index 63240c3962565..c43790b98f38a 100644 --- a/compiler-rt/test/lsan/TestCases/Posix/lit.local.cfg.py +++ b/compiler-rt/test/lsan/TestCases/Posix/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os in ["Windows"]: +if root.target_os in ["Windows"]: config.unsupported = True diff --git a/compiler-rt/test/lsan/lit.common.cfg.py b/compiler-rt/test/lsan/lit.common.cfg.py index 9426b7d108bbf..1e2679438b114 100644 --- a/compiler-rt/test/lsan/lit.common.cfg.py +++ b/compiler-rt/test/lsan/lit.common.cfg.py @@ -34,7 +34,7 @@ def get_required_attr(config, attr_name): config.name = "LeakSanitizer-AddressSanitizer" lsan_cflags = ["-fsanitize=address"] config.available_features.add("asan") - if config.host_os == "NetBSD": + if config.target_os == "NetBSD": config.substitutions.insert(0, ("%run", config.netbsd_noaslr_prefix)) elif lsan_lit_test_mode == "HWAddressSanitizer": config.name = "LeakSanitizer-HWAddressSanitizer" @@ -42,7 +42,7 @@ def get_required_attr(config, attr_name): if target_arch == "x86_64": lsan_cflags = lsan_cflags + ["-fsanitize-hwaddress-experimental-aliasing"] config.available_features.add("hwasan") - if config.host_os == "NetBSD": + if config.target_os == "NetBSD": config.substitutions.insert(0, ("%run", config.netbsd_noaslr_prefix)) else: lit_config.fatal("Unknown LSan test mode: %r" % lsan_lit_test_mode) @@ -51,7 +51,7 @@ def get_required_attr(config, attr_name): # Platform-specific default LSAN_OPTIONS for lit tests. default_common_opts_str = ":".join(list(config.default_sanitizer_opts)) default_lsan_opts = default_common_opts_str + ":detect_leaks=1" -if config.host_os == "Darwin": +if config.target_os == "Darwin": # On Darwin, we default to `abort_on_error=1`, which would make tests run # much slower. Let's override this and run lit tests with 'abort_on_error=0'. # Also, make sure we do not overwhelm the syslog while testing. @@ -101,7 +101,7 @@ def build_invocation(compile_flags): ) supported_linux = ( (not config.android) - and config.host_os == "Linux" + and config.target_os == "Linux" and config.host_arch in [ "aarch64", @@ -117,8 +117,8 @@ def build_invocation(compile_flags): "loongarch64", ] ) -supported_darwin = config.host_os == "Darwin" and config.target_arch in ["x86_64"] -supported_netbsd = config.host_os == "NetBSD" and config.target_arch in [ +supported_darwin = config.target_os == "Darwin" and config.target_arch in ["x86_64"] +supported_netbsd = config.target_os == "NetBSD" and config.target_arch in [ "x86_64", "i386", ] diff --git a/compiler-rt/test/memprof/lit.cfg.py b/compiler-rt/test/memprof/lit.cfg.py index 4057da0c65b51..e28507be4dc9e 100644 --- a/compiler-rt/test/memprof/lit.cfg.py +++ b/compiler-rt/test/memprof/lit.cfg.py @@ -106,7 +106,7 @@ def build_invocation(compile_flags): config.substitutions.append(("%pie", "-pie")) # Only run the tests on supported OSs. -if config.host_os not in ["Linux"]: +if config.target_os not in ["Linux"]: config.unsupported = True if not config.parallelism_group: diff --git a/compiler-rt/test/metadata/lit.cfg.py b/compiler-rt/test/metadata/lit.cfg.py index 73ba27ad3a4e2..9980e93b3a6ec 100644 --- a/compiler-rt/test/metadata/lit.cfg.py +++ b/compiler-rt/test/metadata/lit.cfg.py @@ -5,5 +5,5 @@ config.suffixes = [".cpp"] # Binary metadata is currently emitted only for ELF binaries # and sizes of stack arguments depend on the arch. -if config.host_os not in ["Linux"] or config.target_arch not in ["x86_64"]: +if config.target_os not in ["Linux"] or config.target_arch not in ["x86_64"]: config.unsupported = True diff --git a/compiler-rt/test/msan/Linux/lit.local.cfg.py b/compiler-rt/test/msan/Linux/lit.local.cfg.py index 603ca0365068f..3ea05fa044356 100644 --- a/compiler-rt/test/msan/Linux/lit.local.cfg.py +++ b/compiler-rt/test/msan/Linux/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ["Linux"]: +if root.target_os not in ["Linux"]: config.unsupported = True diff --git a/compiler-rt/test/msan/lit.cfg.py b/compiler-rt/test/msan/lit.cfg.py index 361be79e2557e..d9e83c67b84c8 100644 --- a/compiler-rt/test/msan/lit.cfg.py +++ b/compiler-rt/test/msan/lit.cfg.py @@ -20,7 +20,7 @@ + config.debug_info_flags ) # Some Msan tests leverage backtrace() which requires libexecinfo on FreeBSD. -if config.host_os == "FreeBSD": +if config.target_os == "FreeBSD": clang_msan_cflags += ["-lexecinfo", "-fPIC"] # On SystemZ we need -mbackchain to make the fast unwinder work. if config.target_arch == "s390x": @@ -44,7 +44,7 @@ def build_invocation(compile_flags): # Default test suffixes. config.suffixes = [".c", ".cpp"] -if config.host_os not in ["Linux", "NetBSD", "FreeBSD"]: +if config.target_os not in ["Linux", "NetBSD", "FreeBSD"]: config.unsupported = True # For mips64, mips64el we have forced store_context_size to 1 because these @@ -55,5 +55,5 @@ def build_invocation(compile_flags): else: config.substitutions.append(("CHECK-%short-stack", "CHECK-FULL-STACK")) -if config.host_os == "NetBSD": +if config.target_os == "NetBSD": config.substitutions.insert(0, ("%run", config.netbsd_noaslr_prefix)) diff --git a/compiler-rt/test/nsan/lit.cfg.py b/compiler-rt/test/nsan/lit.cfg.py index 2d67911a7d5d8..8225c85c41b81 100644 --- a/compiler-rt/test/nsan/lit.cfg.py +++ b/compiler-rt/test/nsan/lit.cfg.py @@ -32,5 +32,5 @@ def build_invocation(compile_flags): ) # NSan tests are currently supported on Linux only. -if config.host_os not in ["Linux"]: +if config.target_os not in ["Linux"]: config.unsupported = True diff --git a/compiler-rt/test/orc/TestCases/Darwin/lit.local.cfg.py b/compiler-rt/test/orc/TestCases/Darwin/lit.local.cfg.py index b455a936e7cc1..2e3d36c446714 100644 --- a/compiler-rt/test/orc/TestCases/Darwin/lit.local.cfg.py +++ b/compiler-rt/test/orc/TestCases/Darwin/lit.local.cfg.py @@ -1,2 +1,2 @@ -if config.root.host_os != "Darwin": +if config.root.target_os != "Darwin": config.unsupported = True diff --git a/compiler-rt/test/orc/TestCases/FreeBSD/lit.local.cfg.py b/compiler-rt/test/orc/TestCases/FreeBSD/lit.local.cfg.py index e9b1b38ccacd1..0efdb55dc77f4 100644 --- a/compiler-rt/test/orc/TestCases/FreeBSD/lit.local.cfg.py +++ b/compiler-rt/test/orc/TestCases/FreeBSD/lit.local.cfg.py @@ -1,2 +1,2 @@ -if config.root.host_os != "FreeBSD": +if config.root.target_os != "FreeBSD": config.unsupported = True diff --git a/compiler-rt/test/orc/TestCases/Linux/lit.local.cfg.py b/compiler-rt/test/orc/TestCases/Linux/lit.local.cfg.py index 7d85fa3fce392..32e5cfdb141ae 100644 --- a/compiler-rt/test/orc/TestCases/Linux/lit.local.cfg.py +++ b/compiler-rt/test/orc/TestCases/Linux/lit.local.cfg.py @@ -1,2 +1,2 @@ -if config.root.host_os != "Linux": +if config.root.target_os != "Linux": config.unsupported = True diff --git a/compiler-rt/test/orc/TestCases/Windows/lit.local.cfg.py b/compiler-rt/test/orc/TestCases/Windows/lit.local.cfg.py index 6d4e7da813641..99d4464cf9e77 100644 --- a/compiler-rt/test/orc/TestCases/Windows/lit.local.cfg.py +++ b/compiler-rt/test/orc/TestCases/Windows/lit.local.cfg.py @@ -1,2 +1,2 @@ -if config.root.host_os != "Windows": +if config.root.target_os != "Windows": config.unsupported = True diff --git a/compiler-rt/test/orc/lit.cfg.py b/compiler-rt/test/orc/lit.cfg.py index 7a6eb4e7de325..3c3badb642ff7 100644 --- a/compiler-rt/test/orc/lit.cfg.py +++ b/compiler-rt/test/orc/lit.cfg.py @@ -18,11 +18,11 @@ config.available_features.add("host-arch-compatible") # If the target OS hasn't been set then assume host. -if not config.target_os: - config.target_os = config.host_os +if not config.orc_test_target_os: + config.orc_test_target_os = config.target_os config.test_target_is_host_executable = ( - config.target_os == config.host_os and host_arch_compatible + config.orc_test_target_os == config.target_os and host_arch_compatible ) # Assume that llvm-jitlink is in the config.llvm_tools_dir. @@ -31,7 +31,7 @@ config.compiler_rt_obj_root, "lib/orc/tests/tools/orc-rt-executor" ) lli = os.path.join(config.llvm_tools_dir, "lli") -if config.host_os == "Darwin": +if config.target_os == "Darwin": orc_rt_path = "%s/liborc_rt_osx.a" % config.compiler_rt_libdir else: orc_rt_path = "%s/liborc_rt%s.a" % (config.compiler_rt_libdir, config.target_suffix) @@ -53,7 +53,7 @@ def build_invocation(compile_flags): config.substitutions.append( ("%clang_cl ", build_invocation(["--driver-mode=cl"] + [config.target_cflags])) ) -if config.host_os == "Windows": +if config.target_os == "Windows": config.substitutions.append( ( "%llvm_jitlink", @@ -86,7 +86,7 @@ def build_invocation(compile_flags): # Exclude Inputs directories. config.excludes = ["Inputs"] -if config.host_os not in ["Darwin", "FreeBSD", "Linux", "Windows"]: +if config.target_os not in ["Darwin", "FreeBSD", "Linux", "Windows"]: config.unsupported = True # Ask llvm-config about assertion mode. diff --git a/compiler-rt/test/orc/lit.site.cfg.py.in b/compiler-rt/test/orc/lit.site.cfg.py.in index a33ef3d7d7207..d0625f6ace15c 100644 --- a/compiler-rt/test/orc/lit.site.cfg.py.in +++ b/compiler-rt/test/orc/lit.site.cfg.py.in @@ -5,7 +5,8 @@ config.name_suffix = "@ORC_TEST_CONFIG_SUFFIX@" config.orc_lit_source_dir = "@ORC_LIT_SOURCE_DIR@" config.target_cflags = "@ORC_TEST_TARGET_CFLAGS@" config.target_arch = "@ORC_TEST_TARGET_ARCH@" -config.target_os = "@ORC_TEST_TARGET_OS@" +# FIXME: Remove this variable, the target OS is available in config.target_os. +config.orc_test_target_os = "@ORC_TEST_TARGET_OS@" config.built_with_llvm = ("@COMPILER_RT_STANDALONE_BUILD@" != "TRUE") config.libunwind_shared = "@LIBUNWIND_ENABLE_SHARED@" config.libunwind_install_dir = "@LLVM_BINARY_DIR@/@LIBUNWIND_INSTALL_LIBRARY_DIR@" diff --git a/compiler-rt/test/profile/AIX/lit.local.cfg.py b/compiler-rt/test/profile/AIX/lit.local.cfg.py index 55462708e3b6c..3337c692bd0d7 100644 --- a/compiler-rt/test/profile/AIX/lit.local.cfg.py +++ b/compiler-rt/test/profile/AIX/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ["AIX"]: +if root.target_os not in ["AIX"]: config.unsupported = True diff --git a/compiler-rt/test/profile/Darwin/lit.local.cfg.py b/compiler-rt/test/profile/Darwin/lit.local.cfg.py index 520a963d01198..af82d30cf4de9 100644 --- a/compiler-rt/test/profile/Darwin/lit.local.cfg.py +++ b/compiler-rt/test/profile/Darwin/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ["Darwin"]: +if root.target_os not in ["Darwin"]: config.unsupported = True diff --git a/compiler-rt/test/profile/Linux/lit.local.cfg.py b/compiler-rt/test/profile/Linux/lit.local.cfg.py index c1e89581a1ab9..4bce33db9bbf7 100644 --- a/compiler-rt/test/profile/Linux/lit.local.cfg.py +++ b/compiler-rt/test/profile/Linux/lit.local.cfg.py @@ -42,7 +42,7 @@ def is_gold_linker_available(): root = getRoot(config) -if root.host_os not in ["Linux"] or not is_gold_linker_available(): +if root.target_os not in ["Linux"] or not is_gold_linker_available(): config.unsupported = True if config.have_curl: diff --git a/compiler-rt/test/profile/Posix/lit.local.cfg.py b/compiler-rt/test/profile/Posix/lit.local.cfg.py index 17a67689192d0..62ee3cbb466c4 100644 --- a/compiler-rt/test/profile/Posix/lit.local.cfg.py +++ b/compiler-rt/test/profile/Posix/lit.local.cfg.py @@ -6,12 +6,12 @@ def getRoot(config): root = getRoot(config) -if root.host_os in ["Windows"]: +if root.target_os in ["Windows"]: config.unsupported = True # AIX usually usually makes use of an explicit export list when linking a shared # object, since the linker doesn't export anything by default. -if root.host_os in ["AIX"]: +if root.target_os in ["AIX"]: config.substitutions.append(("%shared_linker_xopts", "-Wl,-bE:shr.exp")) else: config.substitutions.append(("%shared_linker_xopts", "")) diff --git a/compiler-rt/test/profile/Windows/lit.local.cfg.py b/compiler-rt/test/profile/Windows/lit.local.cfg.py index 57c0979e60962..b622e072bcbfb 100644 --- a/compiler-rt/test/profile/Windows/lit.local.cfg.py +++ b/compiler-rt/test/profile/Windows/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ["Windows"]: +if root.target_os not in ["Windows"]: config.unsupported = True diff --git a/compiler-rt/test/profile/lit.cfg.py b/compiler-rt/test/profile/lit.cfg.py index c9a716abeccd8..df7f11e2b286b 100644 --- a/compiler-rt/test/profile/lit.cfg.py +++ b/compiler-rt/test/profile/lit.cfg.py @@ -30,7 +30,7 @@ def get_required_attr(config, attr_name): target_is_msvc = bool(re.match(r".*-windows-msvc$", config.target_triple)) -if config.host_os in ["Linux"]: +if config.target_os in ["Linux"]: extra_link_flags = ["-ldl"] elif target_is_msvc: # InstrProf is incompatible with incremental linking. Disable it as a @@ -154,7 +154,7 @@ def exclude_unsupported_files_for_aix(dirname): ) ) -if config.host_os not in [ +if config.target_os not in [ "Windows", "Darwin", "FreeBSD", @@ -167,10 +167,10 @@ def exclude_unsupported_files_for_aix(dirname): config.unsupported = True config.substitutions.append( - ("%shared_lib_flag", "-dynamiclib" if (config.host_os == "Darwin") else "-shared") + ("%shared_lib_flag", "-dynamiclib" if (config.target_os == "Darwin") else "-shared") ) -if config.host_os in ["AIX"]: +if config.target_os in ["AIX"]: config.available_features.add("system-aix") exclude_unsupported_files_for_aix(config.test_source_root) exclude_unsupported_files_for_aix(config.test_source_root + "/Posix") @@ -184,5 +184,5 @@ def exclude_unsupported_files_for_aix(dirname): if config.have_curl: config.available_features.add("curl") -if config.host_os in ("AIX", "Darwin", "Linux"): +if config.target_os in ("AIX", "Darwin", "Linux"): config.available_features.add("continuous-mode") diff --git a/compiler-rt/test/rtsan/Unit/lit.site.cfg.py.in b/compiler-rt/test/rtsan/Unit/lit.site.cfg.py.in index 59e1e10360b52..41fcb32e5009b 100644 --- a/compiler-rt/test/rtsan/Unit/lit.site.cfg.py.in +++ b/compiler-rt/test/rtsan/Unit/lit.site.cfg.py.in @@ -15,7 +15,7 @@ config.test_source_root = config.test_exec_root if not config.parallelism_group: config.parallelism_group = 'shadow-memory' -if config.host_os == 'Darwin': +if config.target_os == 'Darwin': # On Darwin, we default to ignore_noninstrumented_modules=1, which also # suppresses some races the tests are supposed to find. See rtsan/lit.cfg.py. if 'RTSAN_OPTIONS' in config.environment: diff --git a/compiler-rt/test/rtsan/lit.cfg.py b/compiler-rt/test/rtsan/lit.cfg.py index 7c75515a7608d..6d880c10ecd45 100644 --- a/compiler-rt/test/rtsan/lit.cfg.py +++ b/compiler-rt/test/rtsan/lit.cfg.py @@ -6,7 +6,7 @@ default_rtsan_opts = "atexit_sleep_ms=0" -if config.host_os == "Darwin": +if config.target_os == "Darwin": # On Darwin, we default to `abort_on_error=1`, which would make tests run # much slower. Let's override this and run lit tests with 'abort_on_error=0'. default_rtsan_opts += ":abort_on_error=0" @@ -36,7 +36,7 @@ def build_invocation(compile_flags): llvm_rtsan = os.path.join(config.llvm_tools_dir, "llvm-rtsan") # Setup substitutions. -if config.host_os == "Linux": +if config.target_os == "Linux": libdl_flag = "-ldl" else: libdl_flag = "" @@ -52,7 +52,7 @@ def build_invocation(compile_flags): # Default test suffixes. config.suffixes = [".c", ".cpp"] -if config.host_os not in ["Darwin", "FreeBSD", "Linux", "NetBSD", "OpenBSD"]: +if config.target_os not in ["Darwin", "FreeBSD", "Linux", "NetBSD", "OpenBSD"]: config.unsupported = True elif "64" not in config.host_arch: if "arm" in config.host_arch: @@ -61,5 +61,5 @@ def build_invocation(compile_flags): else: config.unsupported = True -if config.host_os == "NetBSD": +if config.target_os == "NetBSD": config.substitutions.insert(0, ("%run", config.netbsd_nomprotect_prefix)) diff --git a/compiler-rt/test/safestack/lit.cfg.py b/compiler-rt/test/safestack/lit.cfg.py index 4ab9c1ce70bac..3f5565caa65c6 100644 --- a/compiler-rt/test/safestack/lit.cfg.py +++ b/compiler-rt/test/safestack/lit.cfg.py @@ -33,5 +33,5 @@ ) ) -if config.host_os not in ["Linux", "FreeBSD", "NetBSD", "SunOS"]: +if config.target_os not in ["Linux", "FreeBSD", "NetBSD", "SunOS"]: config.unsupported = True diff --git a/compiler-rt/test/sanitizer_common/TestCases/Darwin/lit.local.cfg.py b/compiler-rt/test/sanitizer_common/TestCases/Darwin/lit.local.cfg.py index 520a963d01198..af82d30cf4de9 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Darwin/lit.local.cfg.py +++ b/compiler-rt/test/sanitizer_common/TestCases/Darwin/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ["Darwin"]: +if root.target_os not in ["Darwin"]: config.unsupported = True diff --git a/compiler-rt/test/sanitizer_common/TestCases/FreeBSD/lit.local.cfg.py b/compiler-rt/test/sanitizer_common/TestCases/FreeBSD/lit.local.cfg.py index 0102001660cf1..d4948f04ef64e 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/FreeBSD/lit.local.cfg.py +++ b/compiler-rt/test/sanitizer_common/TestCases/FreeBSD/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ["FreeBSD"]: +if root.target_os not in ["FreeBSD"]: config.unsupported = True diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/lit.local.cfg.py b/compiler-rt/test/sanitizer_common/TestCases/Linux/lit.local.cfg.py index 603ca0365068f..3ea05fa044356 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Linux/lit.local.cfg.py +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ["Linux"]: +if root.target_os not in ["Linux"]: config.unsupported = True diff --git a/compiler-rt/test/sanitizer_common/TestCases/NetBSD/lit.local.cfg.py b/compiler-rt/test/sanitizer_common/TestCases/NetBSD/lit.local.cfg.py index 3cd1aa667343c..aa4438d04380a 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/NetBSD/lit.local.cfg.py +++ b/compiler-rt/test/sanitizer_common/TestCases/NetBSD/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ["NetBSD"]: +if root.target_os not in ["NetBSD"]: config.unsupported = True diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/lit.local.cfg.py b/compiler-rt/test/sanitizer_common/TestCases/Posix/lit.local.cfg.py index 63240c3962565..c43790b98f38a 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Posix/lit.local.cfg.py +++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os in ["Windows"]: +if root.target_os in ["Windows"]: config.unsupported = True diff --git a/compiler-rt/test/sanitizer_common/lit.common.cfg.py b/compiler-rt/test/sanitizer_common/lit.common.cfg.py index 88d3ea9bc5ad2..5614229d9a126 100644 --- a/compiler-rt/test/sanitizer_common/lit.common.cfg.py +++ b/compiler-rt/test/sanitizer_common/lit.common.cfg.py @@ -40,7 +40,7 @@ config.available_features.add(config.tool_name) if ( - config.host_os == "Linux" + config.target_os == "Linux" and config.tool_name == "lsan" and config.target_arch == "i386" ): @@ -49,7 +49,7 @@ if config.arm_thumb: config.available_features.add("thumb") -if config.host_os == "Darwin": +if config.target_os == "Darwin": # On Darwin, we default to `abort_on_error=1`, which would make tests run # much slower. Let's override this and run lit tests with 'abort_on_error=0'. default_tool_options += ["abort_on_error=0"] @@ -68,7 +68,7 @@ extra_link_flags = [] -if config.host_os in ["Linux"]: +if config.target_os in ["Linux"]: extra_link_flags += ["-ldl"] clang_cflags = config.debug_info_flags + tool_cflags + [config.target_cflags] @@ -92,13 +92,13 @@ def build_invocation(compile_flags): config.suffixes = [".c", ".cpp"] -if config.host_os not in ["Linux", "Darwin", "NetBSD", "FreeBSD", "SunOS"]: +if config.target_os not in ["Linux", "Darwin", "NetBSD", "FreeBSD", "SunOS"]: config.unsupported = True if not config.parallelism_group: config.parallelism_group = "shadow-memory" -if config.host_os == "NetBSD": +if config.target_os == "NetBSD": config.substitutions.insert(0, ("%run", config.netbsd_noaslr_prefix)) if os.path.exists("/etc/services"): diff --git a/compiler-rt/test/scudo/lit.cfg.py b/compiler-rt/test/scudo/lit.cfg.py index 5d45bd99804c7..b09c996e9ccc5 100644 --- a/compiler-rt/test/scudo/lit.cfg.py +++ b/compiler-rt/test/scudo/lit.cfg.py @@ -70,5 +70,5 @@ def build_invocation(compile_flags): ) # Hardened Allocator tests are currently supported on Linux only. -if config.host_os not in ["Linux"]: +if config.target_os not in ["Linux"]: config.unsupported = True diff --git a/compiler-rt/test/shadowcallstack/lit.cfg.py b/compiler-rt/test/shadowcallstack/lit.cfg.py index 70a6b16174c4b..5b95deb1b0986 100644 --- a/compiler-rt/test/shadowcallstack/lit.cfg.py +++ b/compiler-rt/test/shadowcallstack/lit.cfg.py @@ -32,5 +32,5 @@ ) ) -if config.host_os not in ["Linux"] or config.target_arch not in ["aarch64", "riscv64"]: +if config.target_os not in ["Linux"] or config.target_arch not in ["aarch64", "riscv64"]: config.unsupported = True diff --git a/compiler-rt/test/tsan/Darwin/lit.local.cfg.py b/compiler-rt/test/tsan/Darwin/lit.local.cfg.py index 7bf80ac5e1375..876f0cd638bd2 100644 --- a/compiler-rt/test/tsan/Darwin/lit.local.cfg.py +++ b/compiler-rt/test/tsan/Darwin/lit.local.cfg.py @@ -6,7 +6,7 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ["Darwin"]: +if root.target_os not in ["Darwin"]: config.unsupported = True config.environment["TSAN_OPTIONS"] += ":ignore_noninstrumented_modules=1" diff --git a/compiler-rt/test/tsan/Linux/lit.local.cfg.py b/compiler-rt/test/tsan/Linux/lit.local.cfg.py index 603ca0365068f..3ea05fa044356 100644 --- a/compiler-rt/test/tsan/Linux/lit.local.cfg.py +++ b/compiler-rt/test/tsan/Linux/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ["Linux"]: +if root.target_os not in ["Linux"]: config.unsupported = True diff --git a/compiler-rt/test/tsan/Unit/lit.site.cfg.py.in b/compiler-rt/test/tsan/Unit/lit.site.cfg.py.in index a9c6261ba48d4..b90af4f2c0d3a 100644 --- a/compiler-rt/test/tsan/Unit/lit.site.cfg.py.in +++ b/compiler-rt/test/tsan/Unit/lit.site.cfg.py.in @@ -15,7 +15,7 @@ config.test_source_root = config.test_exec_root if not config.parallelism_group: config.parallelism_group = 'shadow-memory' -if config.host_os == 'Darwin': +if config.target_os == 'Darwin': # On Darwin, we default to ignore_noninstrumented_modules=1, which also # suppresses some races the tests are supposed to find. See tsan/lit.cfg.py. if 'TSAN_OPTIONS' in config.environment: diff --git a/compiler-rt/test/tsan/libcxx/lit.local.cfg.py b/compiler-rt/test/tsan/libcxx/lit.local.cfg.py index f4820dccb0109..b8d054e2de976 100644 --- a/compiler-rt/test/tsan/libcxx/lit.local.cfg.py +++ b/compiler-rt/test/tsan/libcxx/lit.local.cfg.py @@ -8,5 +8,5 @@ def getRoot(config): # Only run if we have an instrumented libcxx. On Darwin, run always (we have # interceptors to support the system-provided libcxx). -if not root.has_libcxx and root.host_os != "Darwin": +if not root.has_libcxx and root.target_os != "Darwin": config.unsupported = True diff --git a/compiler-rt/test/tsan/libdispatch/lit.local.cfg.py b/compiler-rt/test/tsan/libdispatch/lit.local.cfg.py index a7653f4305952..27edf611a0522 100644 --- a/compiler-rt/test/tsan/libdispatch/lit.local.cfg.py +++ b/compiler-rt/test/tsan/libdispatch/lit.local.cfg.py @@ -14,5 +14,5 @@ def getRoot(config): else: config.unsupported = True -if config.host_os == "Darwin": +if config.target_os == "Darwin": config.environment["TSAN_OPTIONS"] += ":ignore_noninstrumented_modules=1" diff --git a/compiler-rt/test/tsan/lit.cfg.py b/compiler-rt/test/tsan/lit.cfg.py index a93333e2e593d..8803a7bda9aa5 100644 --- a/compiler-rt/test/tsan/lit.cfg.py +++ b/compiler-rt/test/tsan/lit.cfg.py @@ -23,7 +23,7 @@ def get_required_attr(config, attr_name): # Setup environment variables for running ThreadSanitizer. default_tsan_opts = "atexit_sleep_ms=0" -if config.host_os == "Darwin": +if config.target_os == "Darwin": # On Darwin, we default to `abort_on_error=1`, which would make tests run # much slower. Let's override this and run lit tests with 'abort_on_error=0'. default_tsan_opts += ":abort_on_error=0" @@ -61,7 +61,7 @@ def get_required_attr(config, attr_name): ) # Add additional flags if we're using instrumented libc++. # Instrumented libcxx currently not supported on Darwin. -if config.has_libcxx and config.host_os != "Darwin": +if config.has_libcxx and config.target_os != "Darwin": # FIXME: Dehardcode this path somehow. libcxx_path = os.path.join( config.compiler_rt_obj_root, @@ -86,7 +86,7 @@ def build_invocation(compile_flags): config.substitutions.append(("%clangxx_tsan ", build_invocation(clang_tsan_cxxflags))) # Define CHECK-%os to check for OS-dependent output. -config.substitutions.append(("CHECK-%os", ("CHECK-" + config.host_os))) +config.substitutions.append(("CHECK-%os", ("CHECK-" + config.target_os))) config.substitutions.append( ( @@ -101,7 +101,7 @@ def build_invocation(compile_flags): # Default test suffixes. config.suffixes = [".c", ".cpp", ".m", ".mm"] -if config.host_os not in ["FreeBSD", "Linux", "Darwin", "NetBSD"]: +if config.target_os not in ["FreeBSD", "Linux", "Darwin", "NetBSD"]: config.unsupported = True if config.android: @@ -110,5 +110,5 @@ def build_invocation(compile_flags): if not config.parallelism_group: config.parallelism_group = "shadow-memory" -if config.host_os == "NetBSD": +if config.target_os == "NetBSD": config.substitutions.insert(0, ("%run", config.netbsd_noaslr_prefix)) diff --git a/compiler-rt/test/tysan/lit.cfg.py b/compiler-rt/test/tysan/lit.cfg.py index f38e0211639da..26846017b1957 100644 --- a/compiler-rt/test/tysan/lit.cfg.py +++ b/compiler-rt/test/tysan/lit.cfg.py @@ -71,7 +71,7 @@ def push_dynamic_library_lookup_path(config, new_path): # Setup source root. config.test_source_root = os.path.dirname(__file__) -if config.host_os not in ["FreeBSD", "NetBSD"]: +if config.target_os not in ["FreeBSD", "NetBSD"]: libdl_flag = "-ldl" else: libdl_flag = "" @@ -127,10 +127,10 @@ def build_invocation(compile_flags): # Default test suffixes. config.suffixes = [".c", ".cpp"] -if config.host_os == "Darwin": +if config.target_os == "Darwin": config.suffixes.append(".mm") -if config.host_os == "Windows": +if config.target_os == "Windows": config.substitutions.append(("%fPIC", "")) config.substitutions.append(("%fPIE", "")) config.substitutions.append(("%pie", "")) @@ -140,7 +140,7 @@ def build_invocation(compile_flags): config.substitutions.append(("%pie", "-pie")) # Only run the tests on supported OSs. -if config.host_os not in [ +if config.target_os not in [ "Linux", "Darwin", ]: diff --git a/compiler-rt/test/ubsan/TestCases/Misc/Posix/lit.local.cfg.py b/compiler-rt/test/ubsan/TestCases/Misc/Posix/lit.local.cfg.py index 63240c3962565..c43790b98f38a 100644 --- a/compiler-rt/test/ubsan/TestCases/Misc/Posix/lit.local.cfg.py +++ b/compiler-rt/test/ubsan/TestCases/Misc/Posix/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os in ["Windows"]: +if root.target_os in ["Windows"]: config.unsupported = True diff --git a/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/lit.local.cfg.py b/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/lit.local.cfg.py index e69d15f5b141c..4342649532865 100644 --- a/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/lit.local.cfg.py +++ b/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/lit.local.cfg.py @@ -1,4 +1,4 @@ -if config.host_os not in ["Darwin", "FreeBSD", "Linux", "NetBSD"]: +if config.target_os not in ["Darwin", "FreeBSD", "Linux", "NetBSD"]: config.unsupported = True # Work around "Cannot represent a difference across sections" if config.target_arch == "powerpc64": diff --git a/compiler-rt/test/ubsan/TestCases/TypeCheck/Linux/lit.local.cfg.py b/compiler-rt/test/ubsan/TestCases/TypeCheck/Linux/lit.local.cfg.py index 603ca0365068f..3ea05fa044356 100644 --- a/compiler-rt/test/ubsan/TestCases/TypeCheck/Linux/lit.local.cfg.py +++ b/compiler-rt/test/ubsan/TestCases/TypeCheck/Linux/lit.local.cfg.py @@ -6,5 +6,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ["Linux"]: +if root.target_os not in ["Linux"]: config.unsupported = True diff --git a/compiler-rt/test/ubsan/lit.common.cfg.py b/compiler-rt/test/ubsan/lit.common.cfg.py index 04d6f24de5a9f..25e527903788e 100644 --- a/compiler-rt/test/ubsan/lit.common.cfg.py +++ b/compiler-rt/test/ubsan/lit.common.cfg.py @@ -74,7 +74,7 @@ def build_invocation(compile_flags): config.suffixes = [".c", ".cpp", ".m"] # Check that the host supports UndefinedBehaviorSanitizer tests -if config.host_os not in [ +if config.target_os not in [ "Linux", "Darwin", "FreeBSD", @@ -90,5 +90,5 @@ def build_invocation(compile_flags): if ubsan_lit_test_mode in ["AddressSanitizer", "MemorySanitizer", "ThreadSanitizer"]: if not config.parallelism_group: config.parallelism_group = "shadow-memory" - if config.host_os == "NetBSD": + if config.target_os == "NetBSD": config.substitutions.insert(0, ("%run", config.netbsd_noaslr_prefix)) diff --git a/compiler-rt/test/ubsan_minimal/lit.common.cfg.py b/compiler-rt/test/ubsan_minimal/lit.common.cfg.py index 714241a580f9d..bcc0e46fbef91 100644 --- a/compiler-rt/test/ubsan_minimal/lit.common.cfg.py +++ b/compiler-rt/test/ubsan_minimal/lit.common.cfg.py @@ -35,7 +35,7 @@ def build_invocation(compile_flags): config.suffixes = [".c", ".cpp"] # Check that the host supports UndefinedBehaviorSanitizerMinimal tests -if config.host_os not in [ +if config.target_os not in [ "Linux", "FreeBSD", "NetBSD", diff --git a/compiler-rt/test/xray/lit.cfg.py b/compiler-rt/test/xray/lit.cfg.py index f73ae3acd7715..e56ed85d1d822 100644 --- a/compiler-rt/test/xray/lit.cfg.py +++ b/compiler-rt/test/xray/lit.cfg.py @@ -14,7 +14,7 @@ # If libc++ was used to build XRAY libraries, libc++ is needed. Fix applied # to Linux only since -rpath may not be portable. This can be extended to # other platforms. -if config.libcxx_used == "1" and config.host_os == "Linux": +if config.libcxx_used == "1" and config.target_os == "Linux": clang_xray_cflags = clang_xray_cflags + ( ["-L%s -lc++ -Wl,-rpath=%s" % (config.llvm_shlib_dir, config.llvm_shlib_dir)] ) @@ -30,7 +30,7 @@ def build_invocation(compile_flags): llvm_xray = os.path.join(config.llvm_tools_dir, "llvm-xray") # Setup substitutions. -if config.host_os == "Linux": +if config.target_os == "Linux": libdl_flag = "-ldl" else: libdl_flag = "" @@ -56,7 +56,7 @@ def build_invocation(compile_flags): # Default test suffixes. config.suffixes = [".c", ".cpp"] -if config.host_os not in ["FreeBSD", "Linux", "NetBSD", "OpenBSD"]: +if config.target_os not in ["FreeBSD", "Linux", "NetBSD", "OpenBSD"]: config.unsupported = True elif "64" not in config.host_arch: if "arm" in config.host_arch: @@ -65,5 +65,5 @@ def build_invocation(compile_flags): else: config.unsupported = True -if config.host_os == "NetBSD": +if config.target_os == "NetBSD": config.substitutions.insert(0, ("%run", config.netbsd_nomprotect_prefix)) diff --git a/compiler-rt/unittests/lit.common.unit.cfg.py b/compiler-rt/unittests/lit.common.unit.cfg.py index 557a42893ec15..93f417c1d50ae 100644 --- a/compiler-rt/unittests/lit.common.unit.cfg.py +++ b/compiler-rt/unittests/lit.common.unit.cfg.py @@ -42,7 +42,7 @@ def get_lit_conf(name, default=None): if "TEMP" in os.environ: config.environment["TEMP"] = os.environ["TEMP"] -if config.host_os == "Darwin": +if config.target_os == "Darwin": # Only run up to 3 processes that require shadow memory simultaneously on # 64-bit Darwin. Using more scales badly and hogs the system due to # inefficient handling of large mmap'd regions (terabytes) by the kernel. diff --git a/compiler-rt/unittests/lit.common.unit.configured.in b/compiler-rt/unittests/lit.common.unit.configured.in index 3e42e83c9e70a..30ccf452ac71f 100644 --- a/compiler-rt/unittests/lit.common.unit.configured.in +++ b/compiler-rt/unittests/lit.common.unit.configured.in @@ -10,7 +10,7 @@ config.compiler_rt_libdir = lit_config.substitute("@COMPILER_RT_RESOLVED_LIBRARY config.enable_per_target_runtime_dir = @LLVM_ENABLE_PER_TARGET_RUNTIME_DIR_PYBOOL@ config.llvm_build_mode = lit_config.substitute("@LLVM_BUILD_MODE@") config.host_arch = "@HOST_ARCH@" -config.host_os = "@HOST_OS@" +config.target_os = "@HOST_OS@" config.llvm_lib_dir = "@LLVM_LIBRARY_DIR@" config.gwp_asan = @COMPILER_RT_HAS_GWP_ASAN_PYBOOL@ config.emulator = "@COMPILER_RT_EMULATOR@" diff --git a/cross-project-tests/dtlto/link-archive-thin.test b/cross-project-tests/dtlto/link-archive-thin.test new file mode 100644 index 0000000000000..fbd8fd67300cf --- /dev/null +++ b/cross-project-tests/dtlto/link-archive-thin.test @@ -0,0 +1,93 @@ +REQUIRES: lld-link + +## Test that a DTLTO link succeeds and outputs the expected set of files +## correctly when thin archives are present. + +RUN: rm -rf %t && split-file %s %t && cd %t + +## Compile bitcode. -O2 is required for cross-module importing. +RUN: %clang -O2 --target=x86_64-pc-windows-msvc -flto=thin -c \ +RUN: foo.c bar.c dog.c cat.c start.c + +## Generate thin archives. +RUN: lld-link /lib /llvmlibthin /out:foo.lib foo.o +## Create this bitcode thin archive in a subdirectory to test the expansion of +## the path to a bitcode file that is referenced using "..", e.g., in this case +## "../bar.o". +RUN: mkdir lib +RUN: lld-link /lib /llvmlibthin /out:lib/bar.lib bar.o +## Create this bitcode thin archive with an absolute path entry containing "..". +RUN: lld-link /lib /llvmlibthin /out:dog.lib %t/lib/../dog.o +RUN: lld-link /lib /llvmlibthin /out:cat.lib cat.o +RUN: lld-link /lib /llvmlibthin /out:start.lib start.o + +## Link from a different directory to ensure that thin archive member paths are +## resolved correctly relative to the archive locations. +RUN: mkdir %t/out && cd %t/out +RUN: lld-link /subsystem:console /machine:x64 /entry:start /out:my.exe \ +RUN: %t/foo.lib %t/lib/bar.lib ../start.lib %t/cat.lib \ +RUN: /includeoptional:dog ../dog.lib \ +RUN: -thinlto-distributor:%python \ +RUN: -thinlto-distributor-arg:%llvm_src_root/utils/dtlto/local.py \ +RUN: -thinlto-remote-compiler:%clang \ +RUN: /lldsavetemps + +## Check that the required output files have been created. +RUN: ls | FileCheck %s --check-prefix=OUTPUTS --implicit-check-not=cat + +## JSON jobs description. +OUTPUTS-DAG: my.[[PID:[a-zA-Z0-9_]+]].dist-file.json + +## Individual summary index files. +OUTPUTS-DAG: start.1.[[PID]].native.o.thinlto.bc{{$}} +OUTPUTS-DAG: dog.2.[[PID]].native.o.thinlto.bc{{$}} +OUTPUTS-DAG: foo.3.[[PID]].native.o.thinlto.bc{{$}} +OUTPUTS-DAG: bar.4.[[PID]].native.o.thinlto.bc{{$}} + +## Native output object files. +OUTPUTS-DAG: start.1.[[PID]].native.o{{$}} +OUTPUTS-DAG: dog.2.[[PID]].native.o{{$}} +OUTPUTS-DAG: foo.3.[[PID]].native.o{{$}} +OUTPUTS-DAG: bar.4.[[PID]].native.o{{$}} + + +## It is important that cross-module inlining occurs for this test to show that Clang can +## successfully load the bitcode file dependencies recorded in the summary indices. +## Explicitly check that the expected importing has occurred. + +RUN: llvm-dis start.1.*.native.o.thinlto.bc -o - | \ +RUN: FileCheck %s --check-prefixes=FOO,BAR,START + +RUN: llvm-dis dog.2.*.native.o.thinlto.bc -o - | \ +RUN: FileCheck %s --check-prefixes=FOO,BAR,DOG,START + +RUN: llvm-dis foo.3.*.native.o.thinlto.bc -o - | \ +RUN: FileCheck %s --check-prefixes=FOO,BAR,START + +RUN: llvm-dis bar.4.*.native.o.thinlto.bc -o - | \ +RUN: FileCheck %s --check-prefixes=FOO,BAR,START + +FOO-DAG: foo.o +BAR-DAG: bar.o +DOG-DAG: dog.o +START-DAG: start.o + + +#--- foo.c +extern int bar(int), start(int); +__attribute__((retain)) int foo(int x) { return x + bar(x) + start(x); } + +#--- bar.c +extern int foo(int), start(int); +__attribute__((retain)) int bar(int x) { return x + foo(x) + start(x); } + +#--- dog.c +extern int foo(int), bar(int), start(int); +__attribute__((retain)) int dog(int x) { return x + foo(x) + bar(x) + start(x); } + +#--- cat.c +__attribute__((retain)) void cat(int x) {} + +#--- start.c +extern int foo(int), bar(int); +__attribute__((retain)) int start(int x) { return x + foo(x) + bar(x); } diff --git a/cross-project-tests/dtlto/link-dtlto.c b/cross-project-tests/dtlto/link-dtlto.c new file mode 100644 index 0000000000000..0ab4ec57f115d --- /dev/null +++ b/cross-project-tests/dtlto/link-dtlto.c @@ -0,0 +1,41 @@ +// REQUIRES: lld-link + +/// Simple test that DTLTO works with a single input bitcode file and that +/// --save-temps can be applied to the remote compilation. + +// RUN: rm -rf %t && mkdir %t && cd %t + +// RUN: %clang --target=x86_64-pc-windows-msvc -c -flto=thin %s -o dtlto.obj + +// RUN: lld-link /subsystem:console /entry:_start dtlto.obj \ +// RUN: -thinlto-distributor:%python \ +// RUN: -thinlto-distributor-arg:%llvm_src_root/utils/dtlto/local.py \ +// RUN: -thinlto-remote-compiler:%clang \ +// RUN: -thinlto-remote-compiler-arg:--save-temps + +/// Check that the required output files have been created. +// RUN: ls | sort | FileCheck %s + +/// No files are expected before. +// CHECK-NOT: {{.}} + +/// Linked ELF. +// CHECK: {{^}}dtlto.exe{{$}} + +/// Produced by the bitcode compilation. +// CHECK-NEXT: {{^}}dtlto.obj{{$}} + +/// --save-temps output for the backend compilation. +// CHECK-NEXT: {{^}}dtlto.s{{$}} +// CHECK-NEXT: {{^}}dtlto.s.0.preopt.bc{{$}} +// CHECK-NEXT: {{^}}dtlto.s.1.promote.bc{{$}} +// CHECK-NEXT: {{^}}dtlto.s.2.internalize.bc{{$}} +// CHECK-NEXT: {{^}}dtlto.s.3.import.bc{{$}} +// CHECK-NEXT: {{^}}dtlto.s.4.opt.bc{{$}} +// CHECK-NEXT: {{^}}dtlto.s.5.precodegen.bc{{$}} +// CHECK-NEXT: {{^}}dtlto.s.resolution.txt{{$}} + +/// No files are expected after. +// CHECK-NOT: {{.}} + +int _start() { return 0; } diff --git a/cross-project-tests/lit.cfg.py b/cross-project-tests/lit.cfg.py index b35c643ac898c..6a902bc877c89 100644 --- a/cross-project-tests/lit.cfg.py +++ b/cross-project-tests/lit.cfg.py @@ -19,7 +19,7 @@ config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell) # suffixes: A list of file extensions to treat as test files. -config.suffixes = [".c", ".cl", ".cpp", ".m"] +config.suffixes = [".c", ".cl", ".cpp", ".m", ".test"] # excludes: A list of directories to exclude from the testsuite. The 'Inputs' # subdirectories contain auxiliary inputs for various tests in their parent @@ -237,15 +237,6 @@ def can_target_host(): dependencies = configure_dexter_substitutions() if all(d in config.available_features for d in dependencies): config.available_features.add("dexter") - llvm_config.with_environment( - "PATHTOCLANG", add_host_triple(llvm_config.config.clang) - ) - llvm_config.with_environment( - "PATHTOCLANGPP", add_host_triple(llvm_config.use_llvm_tool("clang++")) - ) - llvm_config.with_environment( - "PATHTOCLANGCL", add_host_triple(llvm_config.use_llvm_tool("clang-cl")) - ) else: print( "Host triple {} not supported. Skipping dexter tests in the " diff --git a/flang-rt/include/flang-rt/runtime/descriptor.h b/flang-rt/include/flang-rt/runtime/descriptor.h index 68106f3462c9b..bc5a5b5f14697 100644 --- a/flang-rt/include/flang-rt/runtime/descriptor.h +++ b/flang-rt/include/flang-rt/runtime/descriptor.h @@ -478,7 +478,8 @@ class Descriptor { const SubscriptValue *upper = nullptr, const SubscriptValue *stride = nullptr); - RT_API_ATTRS void ApplyMold(const Descriptor &, int rank); + RT_API_ATTRS void ApplyMold( + const Descriptor &, int rank, bool isMonomorphic = false); RT_API_ATTRS void Check() const; diff --git a/flang-rt/include/flang-rt/runtime/non-tbp-dio.h b/flang-rt/include/flang-rt/runtime/non-tbp-dio.h index 99d4113b6c7a8..26849298ec959 100644 --- a/flang-rt/include/flang-rt/runtime/non-tbp-dio.h +++ b/flang-rt/include/flang-rt/runtime/non-tbp-dio.h @@ -34,11 +34,16 @@ namespace Fortran::runtime::io { RT_OFFLOAD_API_GROUP_BEGIN +enum NonTbpDefinedIoFlags { + IsDtvArgPolymorphic = 1 << 0, // first dummy arg is CLASS(T) + DefinedIoInteger8 = 1 << 1, // -fdefault-integer-8 affected UNIT= & IOSTAT= +}; + struct NonTbpDefinedIo { const typeInfo::DerivedType &derivedType; void (*subroutine)(); // null means no non-TBP defined I/O here common::DefinedIo definedIo; - bool isDtvArgPolymorphic; // first dummy arg is CLASS(T) + std::uint8_t flags; }; struct NonTbpDefinedIoTable { diff --git a/flang-rt/include/flang-rt/runtime/type-info.h b/flang-rt/include/flang-rt/runtime/type-info.h index a8d39f4f8a1a3..93bca24a602b4 100644 --- a/flang-rt/include/flang-rt/runtime/type-info.h +++ b/flang-rt/include/flang-rt/runtime/type-info.h @@ -143,9 +143,9 @@ class SpecialBinding { // I/O procedures that are not type-bound. RT_API_ATTRS SpecialBinding(Which which, ProcedurePointer proc, std::uint8_t isArgDescSet, std::uint8_t isTypeBound, - std::uint8_t isArgContiguousSet) + std::uint8_t specialCaseFlag) : which_{which}, isArgDescriptorSet_{isArgDescSet}, - isTypeBound_{isTypeBound}, isArgContiguousSet_{isArgContiguousSet}, + isTypeBound_{isTypeBound}, specialCaseFlag_{specialCaseFlag}, proc_{proc} {} static constexpr RT_API_ATTRS Which RankFinal(int rank) { @@ -153,13 +153,11 @@ class SpecialBinding { } RT_API_ATTRS Which which() const { return which_; } + RT_API_ATTRS bool specialCaseFlag() const { return specialCaseFlag_; } RT_API_ATTRS bool IsArgDescriptor(int zeroBasedArg) const { return (isArgDescriptorSet_ >> zeroBasedArg) & 1; } RT_API_ATTRS bool IsTypeBound() const { return isTypeBound_ != 0; } - RT_API_ATTRS bool IsArgContiguous(int zeroBasedArg) const { - return (isArgContiguousSet_ >> zeroBasedArg) & 1; - } template RT_API_ATTRS PROC GetProc(const Binding *bindings = nullptr) const { if (bindings && isTypeBound_ > 0) { @@ -203,10 +201,10 @@ class SpecialBinding { // When a special binding is type-bound, this is its binding's index (plus 1, // so that 0 signifies that it's not type-bound). std::uint8_t isTypeBound_{0}; - // True when a FINAL subroutine has a dummy argument that is an array that - // is CONTIGUOUS or neither assumed-rank nor assumed-shape. - std::uint8_t isArgContiguousSet_{0}; - + // For a FINAL subroutine, set when it has a dummy argument that is an array + // that is CONTIGUOUS or neither assumed-rank nor assumed-shape. + // For a defined I/O subroutine, set when UNIT= and IOSTAT= are INTEGER(8). + std::uint8_t specialCaseFlag_{0}; ProcedurePointer proc_{nullptr}; }; diff --git a/flang-rt/lib/runtime/assign.cpp b/flang-rt/lib/runtime/assign.cpp index d642ed578b061..7cf4147a94a95 100644 --- a/flang-rt/lib/runtime/assign.cpp +++ b/flang-rt/lib/runtime/assign.cpp @@ -279,13 +279,15 @@ RT_API_ATTRS int AssignTicket::Begin(WorkQueue &workQueue) { if (mustDeallocateLHS) { // Convert the LHS into a temporary, then make it look deallocated. toDeallocate_ = &tempDescriptor_.descriptor(); - persist_ = true; // tempDescriptor_ state must outlive child tickets std::memcpy( reinterpret_cast(toDeallocate_), &to_, to_.SizeInBytes()); to_.set_base_addr(nullptr); if (toDerived_ && (flags_ & NeedFinalization)) { - if (int status{workQueue.BeginFinalize(*toDeallocate_, *toDerived_)}; - status != StatOk && status != StatContinue) { + int status{workQueue.BeginFinalize(*toDeallocate_, *toDerived_)}; + if (status == StatContinue) { + // tempDescriptor_ state must outlive pending child ticket + persist_ = true; + } else if (status != StatOk) { return status; } flags_ &= ~NeedFinalization; @@ -304,6 +306,9 @@ RT_API_ATTRS int AssignTicket::Begin(WorkQueue &workQueue) { if (int stat{ReturnError( workQueue.terminator(), newFrom.Allocate(kNoAsyncObject))}; stat != StatOk) { + if (stat == StatContinue) { + persist_ = true; + } return stat; } if (HasDynamicComponent(*from_)) { @@ -507,6 +512,7 @@ RT_API_ATTRS int AssignTicket::Continue(WorkQueue &workQueue) { } } if (persist_) { + // tempDescriptor_ must outlive pending child ticket(s) done_ = true; return StatContinue; } else { diff --git a/flang-rt/lib/runtime/derived.cpp b/flang-rt/lib/runtime/derived.cpp index bb9a68abef2a7..4ed0baaa3d108 100644 --- a/flang-rt/lib/runtime/derived.cpp +++ b/flang-rt/lib/runtime/derived.cpp @@ -270,7 +270,7 @@ static RT_API_ATTRS void CallFinalSubroutine(const Descriptor &descriptor, StaticDescriptor statDesc; Descriptor ©{statDesc.descriptor()}; const Descriptor *argDescriptor{&descriptor}; - if (descriptor.rank() > 0 && special->IsArgContiguous(0) && + if (descriptor.rank() > 0 && special->specialCaseFlag() && !descriptor.IsContiguous()) { // The FINAL subroutine demands a contiguous array argument, but // this INTENT(OUT) or intrinsic assignment LHS isn't contiguous. diff --git a/flang-rt/lib/runtime/descriptor-io.cpp b/flang-rt/lib/runtime/descriptor-io.cpp index b208cb2c397b3..3868c8ddce19f 100644 --- a/flang-rt/lib/runtime/descriptor-io.cpp +++ b/flang-rt/lib/runtime/descriptor-io.cpp @@ -67,13 +67,29 @@ static RT_API_ATTRS Fortran::common::optional DefinedFormattedIo( ioType, io.mutableModes().inNamelist ? "NAMELIST" : "LISTDIRECTED"); ioTypeLen = runtime::strlen(ioType); } + // V_LIST= argument StaticDescriptor<1, true> vListStatDesc; Descriptor &vListDesc{vListStatDesc.descriptor()}; - vListDesc.Establish(TypeCategory::Integer, sizeof(int), nullptr, 1); - vListDesc.set_base_addr(edit.vList); - vListDesc.GetDimension(0).SetBounds(1, edit.vListEntries); - vListDesc.GetDimension(0).SetByteStride( - static_cast(sizeof(int))); + bool integer8{special.specialCaseFlag()}; + std::int64_t vList64[edit.maxVListEntries]; + if (integer8) { + // Convert v_list values to INTEGER(8) + for (int j{0}; j < edit.vListEntries; ++j) { + vList64[j] = edit.vList[j]; + } + vListDesc.Establish( + TypeCategory::Integer, sizeof(std::int64_t), nullptr, 1); + vListDesc.set_base_addr(vList64); + vListDesc.GetDimension(0).SetBounds(1, edit.vListEntries); + vListDesc.GetDimension(0).SetByteStride( + static_cast(sizeof(std::int64_t))); + } else { + vListDesc.Establish(TypeCategory::Integer, sizeof(int), nullptr, 1); + vListDesc.set_base_addr(edit.vList); + vListDesc.GetDimension(0).SetBounds(1, edit.vListEntries); + vListDesc.GetDimension(0).SetByteStride( + static_cast(sizeof(int))); + } ExternalFileUnit *actualExternal{io.GetExternalFileUnit()}; ExternalFileUnit *external{actualExternal}; if (!external) { @@ -84,8 +100,8 @@ static RT_API_ATTRS Fortran::common::optional DefinedFormattedIo( ChildIo &child{external->PushChildIo(io)}; // Child formatted I/O is nonadvancing by definition (F'2018 12.6.2.4). auto restorer{common::ScopedSet(io.mutableModes().nonAdvancing, true)}; - int unit{external->unitNumber()}; - int ioStat{IostatOk}; + std::int32_t unit{external->unitNumber()}; + std::int32_t ioStat{IostatOk}; char ioMsg[100]; Fortran::common::optional startPos; if (edit.descriptor == DataEdit::DefinedDerivedType && @@ -98,23 +114,45 @@ static RT_API_ATTRS Fortran::common::optional DefinedFormattedIo( derived.binding().OffsetElement()}; if (special.IsArgDescriptor(0)) { // "dtv" argument is "class(t)", pass a descriptor - auto *p{special.GetProc( - bindings)}; StaticDescriptor<1, true, 10 /*?*/> elementStatDesc; Descriptor &elementDesc{elementStatDesc.descriptor()}; elementDesc.Establish( derived, nullptr, 0, nullptr, CFI_attribute_pointer); elementDesc.set_base_addr(descriptor.Element(subscripts)); - p(elementDesc, unit, ioType, vListDesc, ioStat, ioMsg, ioTypeLen, - sizeof ioMsg); + if (integer8) { // 64-bit UNIT=/IOSTAT= + std::int64_t unit64{unit}; + std::int64_t ioStat64{ioStat}; + auto *p{special.GetProc(bindings)}; + p(elementDesc, unit64, ioType, vListDesc, ioStat64, ioMsg, ioTypeLen, + sizeof ioMsg); + ioStat = ioStat64; + } else { // 32-bit UNIT=/IOSTAT= + auto *p{special.GetProc(bindings)}; + p(elementDesc, unit, ioType, vListDesc, ioStat, ioMsg, ioTypeLen, + sizeof ioMsg); + } } else { // "dtv" argument is "type(t)", pass a raw pointer - auto *p{special.GetProc( - bindings)}; - p(descriptor.Element(subscripts), unit, ioType, vListDesc, ioStat, - ioMsg, ioTypeLen, sizeof ioMsg); + if (integer8) { // 64-bit UNIT= and IOSTAT= + std::int64_t unit64{unit}; + std::int64_t ioStat64{ioStat}; + auto *p{special.GetProc(bindings)}; + p(descriptor.Element(subscripts), unit64, ioType, vListDesc, + ioStat64, ioMsg, ioTypeLen, sizeof ioMsg); + ioStat = ioStat64; + } else { // 32-bit UNIT= and IOSTAT= + auto *p{special.GetProc(bindings)}; + p(descriptor.Element(subscripts), unit, ioType, vListDesc, ioStat, + ioMsg, ioTypeLen, sizeof ioMsg); + } } handler.Forward(ioStat, ioMsg, sizeof ioMsg); external->PopChildIo(child); @@ -458,11 +496,16 @@ RT_API_ATTRS int DescriptorIoTicket::Begin(WorkQueue &workQueue) { ? common::DefinedIo::ReadUnformatted : common::DefinedIo::WriteUnformatted)}) { if (definedIo->subroutine) { + std::uint8_t isArgDescriptorSet{0}; + if (definedIo->flags & IsDtvArgPolymorphic) { + isArgDescriptorSet = 1; + } typeInfo::SpecialBinding special{DIR == Direction::Input ? typeInfo::SpecialBinding::Which::ReadUnformatted : typeInfo::SpecialBinding::Which::WriteUnformatted, - definedIo->subroutine, definedIo->isDtvArgPolymorphic, false, - false}; + definedIo->subroutine, isArgDescriptorSet, + /*IsTypeBound=*/false, + /*specialCaseFlag=*/!!(definedIo->flags & DefinedIoInteger8)}; if (DefinedUnformattedIo(io_, instance_, *type, special)) { anyIoTookPlace_ = true; return StatOk; @@ -719,8 +762,11 @@ RT_API_ATTRS int DescriptorIoTicket::Begin(WorkQueue &workQueue) { nonTbpSpecial_.emplace(DIR == Direction::Input ? typeInfo::SpecialBinding::Which::ReadFormatted : typeInfo::SpecialBinding::Which::WriteFormatted, - definedIo->subroutine, definedIo->isDtvArgPolymorphic, false, - false); + definedIo->subroutine, + /*isArgDescriptorSet=*/ + (definedIo->flags & IsDtvArgPolymorphic) ? 1 : 0, + /*isTypeBound=*/false, + /*specialCaseFlag=*/!!(definedIo->flags & DefinedIoInteger8)); special_ = &*nonTbpSpecial_; } } diff --git a/flang-rt/lib/runtime/descriptor.cpp b/flang-rt/lib/runtime/descriptor.cpp index b723acdd27bd5..021440cbdd0f6 100644 --- a/flang-rt/lib/runtime/descriptor.cpp +++ b/flang-rt/lib/runtime/descriptor.cpp @@ -85,7 +85,7 @@ RT_API_ATTRS void Descriptor::Establish(int characterKind, RT_API_ATTRS void Descriptor::Establish(const typeInfo::DerivedType &dt, void *p, int rank, const SubscriptValue *extent, ISO::CFI_attribute_t attribute) { - std::size_t elementBytes{dt.sizeInBytes()}; + auto elementBytes{static_cast(dt.sizeInBytes())}; ISO::EstablishDescriptor( &raw_, p, attribute, CFI_type_struct, elementBytes, rank, extent); if (elementBytes == 0) { @@ -252,18 +252,21 @@ RT_API_ATTRS bool Descriptor::EstablishPointerSection(const Descriptor &source, return CFI_section(&raw_, &source.raw_, lower, upper, stride) == CFI_SUCCESS; } -RT_API_ATTRS void Descriptor::ApplyMold(const Descriptor &mold, int rank) { - raw_.elem_len = mold.raw_.elem_len; +RT_API_ATTRS void Descriptor::ApplyMold( + const Descriptor &mold, int rank, bool isMonomorphic) { raw_.rank = rank; - raw_.type = mold.raw_.type; for (int j{0}; j < rank && j < mold.raw_.rank; ++j) { GetDimension(j) = mold.GetDimension(j); } - if (auto *addendum{Addendum()}) { - if (auto *moldAddendum{mold.Addendum()}) { - *addendum = *moldAddendum; - } else { - INTERNAL_CHECK(!addendum->derivedType()); + if (!isMonomorphic) { + raw_.elem_len = mold.raw_.elem_len; + raw_.type = mold.raw_.type; + if (auto *addendum{Addendum()}) { + if (auto *moldAddendum{mold.Addendum()}) { + *addendum = *moldAddendum; + } else { + INTERNAL_CHECK(!addendum->derivedType()); + } } } } diff --git a/flang-rt/lib/runtime/edit-input.cpp b/flang-rt/lib/runtime/edit-input.cpp index 0cc287aa3b47e..13557678f6057 100644 --- a/flang-rt/lib/runtime/edit-input.cpp +++ b/flang-rt/lib/runtime/edit-input.cpp @@ -19,16 +19,19 @@ namespace Fortran::runtime::io { RT_OFFLOAD_API_GROUP_BEGIN -// Checks that a list-directed input value has been entirely consumed and -// doesn't contain unparsed characters before the next value separator. +// Handle DC or DECIMAL='COMMA' and determine the active separator character +static inline RT_API_ATTRS char32_t GetSeparatorChar(const DataEdit &edit) { + return edit.modes.editingFlags & decimalComma ? char32_t{';'} : char32_t{','}; +} + static inline RT_API_ATTRS bool IsCharValueSeparator( const DataEdit &edit, char32_t ch) { - char32_t comma{ - edit.modes.editingFlags & decimalComma ? char32_t{';'} : char32_t{','}}; - return ch == ' ' || ch == '\t' || ch == comma || ch == '/' || + return ch == ' ' || ch == '\t' || ch == '/' || ch == GetSeparatorChar(edit) || (edit.IsNamelist() && (ch == '&' || ch == '$')); } +// Checks that a list-directed input value has been entirely consumed and +// doesn't contain unparsed characters before the next value separator. static RT_API_ATTRS bool CheckCompleteListDirectedField( IoStatementState &io, const DataEdit &edit) { if (edit.IsListDirected()) { @@ -54,10 +57,6 @@ static RT_API_ATTRS bool CheckCompleteListDirectedField( } } -static inline RT_API_ATTRS char32_t GetSeparatorChar(const DataEdit &edit) { - return edit.modes.editingFlags & decimalComma ? char32_t{';'} : char32_t{','}; -} - template static RT_API_ATTRS bool EditBOZInput( IoStatementState &io, const DataEdit &edit, void *n, std::size_t bytes) { @@ -518,7 +517,7 @@ static RT_API_ATTRS ScannedRealInput ScanRealInput( // Consume the trailing ')' of a list-directed or NAMELIST complex // input value. if (edit.descriptor == DataEdit::ListDirectedImaginaryPart) { - if (next && (*next == ' ' || *next == '\t')) { + if (!next || *next == ' ' || *next == '\t') { io.SkipSpaces(remaining); next = io.NextInField(remaining, edit); } @@ -1006,27 +1005,7 @@ static RT_API_ATTRS bool EditListDirectedCharacterInput( // Undelimited list-directed character input: stop at a value separator // or the end of the current record. while (auto ch{io.GetCurrentChar(byteCount)}) { - bool isSep{false}; - switch (*ch) { - case ' ': - case '\t': - case '/': - isSep = true; - break; - case '&': - case '$': - isSep = edit.IsNamelist(); - break; - case ',': - isSep = !(edit.modes.editingFlags & decimalComma); - break; - case ';': - isSep = !!(edit.modes.editingFlags & decimalComma); - break; - default: - break; - } - if (isSep) { + if (IsCharValueSeparator(edit, *ch)) { break; } if (length > 0) { diff --git a/flang-rt/lib/runtime/extensions.cpp b/flang-rt/lib/runtime/extensions.cpp index e70dff3997233..f6c39468d5655 100644 --- a/flang-rt/lib/runtime/extensions.cpp +++ b/flang-rt/lib/runtime/extensions.cpp @@ -27,10 +27,7 @@ #include #ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#define NOMINMAX -#include - +#include "flang/Common/windows-include.h" #include inline void CtimeBuffer(char *buffer, size_t bufsize, const time_t cur_time, @@ -309,6 +306,9 @@ void RTNAME(Perror)(const char *str) { perror(str); } // GNU extension function TIME() std::int64_t RTNAME(time)() { return time(nullptr); } +// MCLOCK: returns accumulated CPU time in ticks +std::int32_t FORTRAN_PROCEDURE_NAME(mclock)() { return std::clock(); } + // Extension procedures related to I/O namespace io { diff --git a/flang-rt/lib/runtime/non-tbp-dio.cpp b/flang-rt/lib/runtime/non-tbp-dio.cpp index 72101b06e0c6e..d516526033c27 100644 --- a/flang-rt/lib/runtime/non-tbp-dio.cpp +++ b/flang-rt/lib/runtime/non-tbp-dio.cpp @@ -17,7 +17,7 @@ const NonTbpDefinedIo *NonTbpDefinedIoTable::Find( for (const auto *p{item}; j-- > 0; ++p) { if (&p->derivedType == &type && p->definedIo == definedIo) { return p; - } else if (p->isDtvArgPolymorphic) { + } else if (p->flags & IsDtvArgPolymorphic) { for (const typeInfo::DerivedType *t{type.GetParentType()}; t; t = t->GetParentType()) { if (&p->derivedType == t && p->definedIo == definedIo) { diff --git a/flang-rt/lib/runtime/pointer.cpp b/flang-rt/lib/runtime/pointer.cpp index 04487abd3272e..68db2594acdd4 100644 --- a/flang-rt/lib/runtime/pointer.cpp +++ b/flang-rt/lib/runtime/pointer.cpp @@ -87,9 +87,9 @@ void RTDEF(PointerAssociateLowerBounds)(Descriptor &pointer, } } -void RTDEF(PointerAssociateRemapping)(Descriptor &pointer, +static void RT_API_ATTRS PointerRemapping(Descriptor &pointer, const Descriptor &target, const Descriptor &bounds, const char *sourceFile, - int sourceLine) { + int sourceLine, bool isMonomorphic) { Terminator terminator{sourceFile, sourceLine}; SubscriptValue byteStride{/*captured from first dimension*/}; std::size_t boundElementBytes{bounds.ElementBytes()}; @@ -99,7 +99,7 @@ void RTDEF(PointerAssociateRemapping)(Descriptor &pointer, // the ranks may mismatch. Use target as a mold for initializing // the pointer descriptor. INTERNAL_CHECK(static_cast(pointer.rank()) == boundsRank); - pointer.ApplyMold(target, boundsRank); + pointer.ApplyMold(target, boundsRank, isMonomorphic); pointer.set_base_addr(target.raw().base_addr); pointer.raw().attribute = CFI_attribute_pointer; for (unsigned j{0}; j < boundsRank; ++j) { @@ -124,6 +124,19 @@ void RTDEF(PointerAssociateRemapping)(Descriptor &pointer, } } +void RTDEF(PointerAssociateRemapping)(Descriptor &pointer, + const Descriptor &target, const Descriptor &bounds, const char *sourceFile, + int sourceLine) { + PointerRemapping( + pointer, target, bounds, sourceFile, sourceLine, /*isMonomorphic=*/false); +} +void RTDEF(PointerAssociateRemappingMonomorphic)(Descriptor &pointer, + const Descriptor &target, const Descriptor &bounds, const char *sourceFile, + int sourceLine) { + PointerRemapping( + pointer, target, bounds, sourceFile, sourceLine, /*isMonomorphic=*/true); +} + RT_API_ATTRS void *AllocateValidatedPointerPayload( std::size_t byteSize, int allocatorIdx) { // Add space for a footer to validate during deallocation. diff --git a/flang-rt/lib/runtime/type-info.cpp b/flang-rt/lib/runtime/type-info.cpp index 3e1d7c9c3c788..50123f4cf321c 100644 --- a/flang-rt/lib/runtime/type-info.cpp +++ b/flang-rt/lib/runtime/type-info.cpp @@ -330,7 +330,7 @@ FILE *SpecialBinding::Dump(FILE *f) const { } std::fprintf(f, " isArgDescriptorSet: 0x%x\n", isArgDescriptorSet_); std::fprintf(f, " isTypeBound: %d\n", isTypeBound_); - std::fprintf(f, " isArgContiguousSet: 0x%x\n", isArgContiguousSet_); + std::fprintf(f, " specialCaseFlag 0x%x\n", specialCaseFlag_); std::fprintf(f, " proc: %p\n", reinterpret_cast(proc_)); return f; } diff --git a/flang-rt/unittests/Runtime/CUDA/AllocatorCUF.cpp b/flang-rt/unittests/Runtime/CUDA/AllocatorCUF.cpp index 83aa37f8d06f3..d76fca2c4250e 100644 --- a/flang-rt/unittests/Runtime/CUDA/AllocatorCUF.cpp +++ b/flang-rt/unittests/Runtime/CUDA/AllocatorCUF.cpp @@ -79,6 +79,6 @@ TEST(AllocatableCUFTest, CUFSetAllocatorIndex) { // REAL(4), DEVICE, ALLOCATABLE :: a(:) auto a{createAllocatable(TypeCategory::Real, 4)}; EXPECT_EQ((int)kDefaultAllocator, a->GetAllocIdx()); - RTNAME(CUFSetAllocatorIndex)(*a, kDeviceAllocatorPos, __FILE__, __LINE__); + RTNAME(CUFSetAllocatorIndex)(a, kDeviceAllocatorPos, __FILE__, __LINE__); EXPECT_EQ((int)kDeviceAllocatorPos, a->GetAllocIdx()); } diff --git a/flang-rt/unittests/Runtime/NumericalFormatTest.cpp b/flang-rt/unittests/Runtime/NumericalFormatTest.cpp index f1492d0e39fec..73245dca13bc0 100644 --- a/flang-rt/unittests/Runtime/NumericalFormatTest.cpp +++ b/flang-rt/unittests/Runtime/NumericalFormatTest.cpp @@ -213,6 +213,37 @@ TEST(IOApiTests, ListInputTest) { << "', but got '" << output << "'"; } +TEST(IOApiTests, ListInputComplexRegressionTest) { + static const char input[]{"(1,;2, );(3,;4,)"}; + auto cookie{IONAME(BeginInternalListInput)(input, sizeof input - 1)}; + static constexpr int numRealValues{4}; + float z[numRealValues]; + ASSERT_TRUE(IONAME(SetDecimal)(cookie, "COMMA", 5)); + for (int j{0}; j < numRealValues; j += 2) { + ASSERT_TRUE(IONAME(InputComplex32)(cookie, &z[j])) + << "InputComplex32 failed with value " << z[j]; + } + auto status{IONAME(EndIoStatement)(cookie)}; + ASSERT_EQ(status, 0) << "Failed complex list-directed input, status " + << static_cast(status); + static constexpr int bufferSize{18}; + char output[bufferSize]; + output[bufferSize - 1] = '\0'; + cookie = IONAME(BeginInternalListOutput)(output, bufferSize - 1); + for (int j{0}; j < numRealValues; j += 2) { + ASSERT_TRUE(IONAME(OutputComplex32)(cookie, z[j], z[j + 1])) + << "OutputComplex32 failed when outputting value " << z[j] << ", " + << z[j + 1]; + } + status = IONAME(EndIoStatement)(cookie); + ASSERT_EQ(status, 0) << "Failed complex list-directed output, status " + << static_cast(status); + static const char expect[bufferSize]{" (1.,2.) (3.,4.) "}; + ASSERT_EQ(std::strncmp(output, expect, bufferSize), 0) + << "Failed complex list-directed output, expected '" << expect + << "', but got '" << output << "'"; +} + TEST(IOApiTests, DescriptorOutputTest) { static constexpr int bufferSize{10}; char buffer[bufferSize]; diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md index 72d12cd92600d..c167a55bc486d 100644 --- a/flang/docs/Extensions.md +++ b/flang/docs/Extensions.md @@ -1,9 +1,9 @@ - # Fortran Extensions supported by Flang @@ -170,6 +170,18 @@ end In the case of `DEFERRED` bindings in an `ABSTRACT` derived type, however, overrides are necessary, so they are permitted for inaccessible bindings with an optional warning. +* Main program name is allowed to be the same as the other symbols used + in the main program, for example: +``` +module m +end +program m +use m +end +``` + Note that internally the main program symbol name is all uppercase, unlike + the names of all other symbols, which are usually all lowercase. This + may make a difference in testing/debugging. ## Extensions, deletions, and legacy features supported by default diff --git a/flang/docs/GettingStarted.md b/flang/docs/GettingStarted.md index 0b3b551ffbfba..2ea8093b607cf 100644 --- a/flang/docs/GettingStarted.md +++ b/flang/docs/GettingStarted.md @@ -74,15 +74,14 @@ cmake \ -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=$INSTALLDIR \ - -DCMAKE_CXX_STANDARD=17 \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ -DCMAKE_CXX_LINK_FLAGS="-Wl,-rpath,$LD_LIBRARY_PATH" \ -DFLANG_ENABLE_WERROR=ON \ -DLLVM_ENABLE_ASSERTIONS=ON \ -DLLVM_TARGETS_TO_BUILD=host \ -DLLVM_LIT_ARGS=-v \ - -DLLVM_ENABLE_PROJECTS="clang;mlir;flang;openmp" \ - -DLLVM_ENABLE_RUNTIMES="compiler-rt;flang-rt" \ + -DLLVM_ENABLE_PROJECTS="clang;mlir;flang" \ + -DLLVM_ENABLE_RUNTIMES="compiler-rt;flang-rt;openmp" \ ../llvm-project/llvm ninja @@ -141,7 +140,6 @@ cd build cmake \ -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_CXX_STANDARD=17 \ -DCMAKE_CXX_LINK_FLAGS="-Wl,-rpath,$LD_LIBRARY_PATH" \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ -DFLANG_ENABLE_WERROR=ON \ diff --git a/flang/docs/Intrinsics.md b/flang/docs/Intrinsics.md index 0118f8eb7d913..f7da6c889d413 100644 --- a/flang/docs/Intrinsics.md +++ b/flang/docs/Intrinsics.md @@ -709,8 +709,9 @@ CACHESIZE, EOF, FP_CLASS, INT_PTR_KIND, ISNAN, LOC MALLOC, FREE ``` -### Library subroutine +### Library subroutines and functions ``` +ticks = MCLOCK() CALL BACKTRACE() CALL FDATE(TIME) CALL GETLOG(USRNAME) diff --git a/flang/docs/ParallelMultiImageFortranRuntime.md b/flang/docs/ParallelMultiImageFortranRuntime.md new file mode 100644 index 0000000000000..8cf0055e5817b --- /dev/null +++ b/flang/docs/ParallelMultiImageFortranRuntime.md @@ -0,0 +1,18 @@ + + +# Multi-Image Parallel Fortran Runtime + + +The Parallel Runtime Interface for Fortran (PRIF) defines an +interface designed for LLVM Flang to target implementations of +Fortran's multi-image parallel features. + +The current revision of the PRIF specification is here: + + diff --git a/flang/docs/index.md b/flang/docs/index.md index 2568ad70c5d09..016577bcb1e98 100644 --- a/flang/docs/index.md +++ b/flang/docs/index.md @@ -78,6 +78,7 @@ on how to get in touch with us and to learn more about the current status. OpenMP-semantics OptionComparison Overview + ParallelMultiImageFortranRuntime ParameterizedDerivedTypes ParserCombinators Parsing diff --git a/flang/include/flang/Evaluate/integer.h b/flang/include/flang/Evaluate/integer.h index fccc2ad774a8f..5953fc81cb111 100644 --- a/flang/include/flang/Evaluate/integer.h +++ b/flang/include/flang/Evaluate/integer.h @@ -74,6 +74,7 @@ class Integer { static_assert(std::is_unsigned_v); static_assert(CHAR_BIT * sizeof(BigPart) >= 2 * partBits); static constexpr bool littleEndian{IS_LITTLE_ENDIAN}; + static constexpr int alignment{ALIGNMENT}; private: static constexpr int maxPartBits{CHAR_BIT * sizeof(Part)}; diff --git a/flang/include/flang/Evaluate/real.h b/flang/include/flang/Evaluate/real.h index 03294881850a1..76d25d9fe2670 100644 --- a/flang/include/flang/Evaluate/real.h +++ b/flang/include/flang/Evaluate/real.h @@ -490,7 +490,10 @@ template class Real { bool isNegative, int exponent, const Fraction &, Rounding, RoundingBits, bool multiply = false); - Word word_{}; // an Integer<> + // Require alignment, in case code generation on x86_64 decides that our + // Real object is suitable for SSE2 instructions and then gets surprised + // by unaligned address. + alignas(Word::alignment / 8) Word word_{}; // an Integer<> }; extern template class Real, 11>; // IEEE half format diff --git a/flang/include/flang/Lower/Runtime.h b/flang/include/flang/Lower/Runtime.h index 77e98a1e019e7..f76f398569b54 100644 --- a/flang/include/flang/Lower/Runtime.h +++ b/flang/include/flang/Lower/Runtime.h @@ -70,7 +70,7 @@ void genPointerAssociate(fir::FirOpBuilder &, mlir::Location, mlir::Value pointer, mlir::Value target); void genPointerAssociateRemapping(fir::FirOpBuilder &, mlir::Location, mlir::Value pointer, mlir::Value target, - mlir::Value bounds); + mlir::Value bounds, bool isMonomorphic); void genPointerAssociateLowerBounds(fir::FirOpBuilder &, mlir::Location, mlir::Value pointer, mlir::Value target, mlir::Value lbounds); diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h index d38c5b6d09a82..d84d3593ebca6 100644 --- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h +++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h @@ -241,11 +241,11 @@ struct IntrinsicLibrary { void genCFProcPointer(llvm::ArrayRef); fir::ExtendedValue genCFunLoc(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genCLoc(mlir::Type, llvm::ArrayRef); - mlir::Value genClock64(mlir::Type, llvm::ArrayRef); template fir::ExtendedValue genCPtrCompare(mlir::Type, llvm::ArrayRef); mlir::Value genCosd(mlir::Type, llvm::ArrayRef); + mlir::Value genCospi(mlir::Type, llvm::ArrayRef); void genDateAndTime(llvm::ArrayRef); mlir::Value genDim(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genDotProduct(mlir::Type, @@ -376,6 +376,8 @@ struct IntrinsicLibrary { fir::ExtendedValue genNorm2(mlir::Type, llvm::ArrayRef); mlir::Value genNot(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genNull(mlir::Type, llvm::ArrayRef); + template + mlir::Value genNVVMTime(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genPack(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genParity(mlir::Type, llvm::ArrayRef); void genPerror(llvm::ArrayRef); @@ -417,6 +419,7 @@ struct IntrinsicLibrary { mlir::Value genShiftA(mlir::Type resultType, llvm::ArrayRef); mlir::Value genSign(mlir::Type, llvm::ArrayRef); mlir::Value genSind(mlir::Type, llvm::ArrayRef); + mlir::Value genSinpi(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genSize(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genSizeOf(mlir::Type, llvm::ArrayRef); mlir::Value genSpacing(mlir::Type resultType, diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h b/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h index 9ca4b2baeaa65..145ea04e56484 100644 --- a/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h +++ b/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h @@ -37,7 +37,7 @@ void genPointerAssociate(fir::FirOpBuilder &, mlir::Location, mlir::Value pointer, mlir::Value target); void genPointerAssociateRemapping(fir::FirOpBuilder &, mlir::Location, mlir::Value pointer, mlir::Value target, - mlir::Value bounds); + mlir::Value bounds, bool isMonomorphic); mlir::Value genCpuTime(fir::FirOpBuilder &, mlir::Location); void genDateAndTime(fir::FirOpBuilder &, mlir::Location, diff --git a/flang/include/flang/Optimizer/Support/InitFIR.h b/flang/include/flang/Optimizer/Support/InitFIR.h index 8bb4791859bb7..aacba233a2b32 100644 --- a/flang/include/flang/Optimizer/Support/InitFIR.h +++ b/flang/include/flang/Optimizer/Support/InitFIR.h @@ -23,6 +23,7 @@ #include "mlir/Dialect/Affine/Passes.h" #include "mlir/Dialect/Complex/IR/Complex.h" #include "mlir/Dialect/Func/Extensions/InlinerExtension.h" +#include "mlir/Dialect/Index/IR/IndexDialect.h" #include "mlir/Dialect/LLVMIR/NVVMDialect.h" #include "mlir/Dialect/OpenACC/Transforms/Passes.h" #include "mlir/Dialect/SCF/Transforms/Passes.h" @@ -41,7 +42,8 @@ namespace fir::support { mlir::cf::ControlFlowDialect, mlir::func::FuncDialect, \ mlir::vector::VectorDialect, mlir::math::MathDialect, \ mlir::complex::ComplexDialect, mlir::DLTIDialect, cuf::CUFDialect, \ - mlir::NVVM::NVVMDialect, mlir::gpu::GPUDialect + mlir::NVVM::NVVMDialect, mlir::gpu::GPUDialect, \ + mlir::index::IndexDialect #define FLANG_CODEGEN_DIALECT_LIST FIRCodeGenDialect, mlir::LLVM::LLVMDialect diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 32b6ca45609b6..23e35d106c077 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -529,6 +529,8 @@ class ParseTreeDumper { NODE(parser, OmpAlignClause) NODE(parser, OmpAlignedClause) NODE(OmpAlignedClause, Modifier) + NODE(parser, OmpAlwaysModifier) + NODE_ENUM(OmpAlwaysModifier, Value) NODE(parser, OmpAtClause) NODE_ENUM(OmpAtClause, ActionTime) NODE_ENUM(OmpSeverityClause, Severity) @@ -546,6 +548,8 @@ class ParseTreeDumper { #include "llvm/Frontend/OpenMP/OMP.inc" NODE(parser, OmpClauseList) NODE(parser, OmpCancellationConstructTypeClause) + NODE(parser, OmpCloseModifier) + NODE_ENUM(OmpCloseModifier, Value) NODE(parser, OmpContainsClause) NODE(parser, OmpCriticalDirective) NODE(parser, OmpErrorDirective) @@ -561,6 +565,8 @@ class ParseTreeDumper { NODE(parser, OmpDefaultmapClause) NODE_ENUM(OmpDefaultmapClause, ImplicitBehavior) NODE(OmpDefaultmapClause, Modifier) + NODE(parser, OmpDeleteModifier) + NODE_ENUM(OmpDeleteModifier, Value) NODE(parser, OmpDependenceType) NODE_ENUM(OmpDependenceType, Value) NODE(parser, OmpTaskDependenceType) @@ -628,6 +634,8 @@ class ParseTreeDumper { NODE(OmpNumTasksClause, Modifier) NODE(parser, OmpBindClause) NODE_ENUM(OmpBindClause, Binding) + NODE(parser, OmpPresentModifier) + NODE_ENUM(OmpPresentModifier, Value) NODE(parser, OmpProcBindClause) NODE_ENUM(OmpProcBindClause, AffinityPolicy) NODE(parser, OmpReductionModifier) @@ -637,6 +645,10 @@ class ParseTreeDumper { NODE(parser, OmpInReductionClause) NODE(OmpInReductionClause, Modifier) NODE(parser, OmpReductionCombiner) + NODE(parser, OmpRefModifier) + NODE_ENUM(OmpRefModifier, Value) + NODE(parser, OmpSelfModifier) + NODE_ENUM(OmpSelfModifier, Value) NODE(parser, OmpTaskReductionClause) NODE(OmpTaskReductionClause, Modifier) NODE(parser, OmpInitializerProc) @@ -673,6 +685,8 @@ class ParseTreeDumper { NODE(parser, OmpSectionsDirective) NODE(parser, OmpToClause) NODE(OmpToClause, Modifier) + NODE(parser, OmpxHoldModifier) + NODE_ENUM(OmpxHoldModifier, Value) NODE(parser, Only) NODE(parser, OpenACCAtomicConstruct) NODE(parser, OpenACCBlockConstruct) diff --git a/flang/include/flang/Parser/message.h b/flang/include/flang/Parser/message.h index db1a0a65157e3..9192d23529913 100644 --- a/flang/include/flang/Parser/message.h +++ b/flang/include/flang/Parser/message.h @@ -355,9 +355,9 @@ class Messages { void Emit(llvm::raw_ostream &, const AllCookedSources &, bool echoSourceLines = true, const common::LanguageFeatureControl *hintFlags = nullptr, - std::size_t maxErrorsToEmit = 0) const; + std::size_t maxErrorsToEmit = 0, bool warningsAreErrors = false) const; void AttachTo(Message &, std::optional = std::nullopt); - bool AnyFatalError() const; + bool AnyFatalError(bool warningsAreErrors = false) const; private: std::list messages_; diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index cc1d032f94d4a..0b3dec1010312 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3756,6 +3756,19 @@ struct OmpAllocatorComplexModifier { WRAPPER_CLASS_BOILERPLATE(OmpAllocatorComplexModifier, ScalarIntExpr); }; +// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158], +// [6.0:279-288] +// +// always-modifier -> +// ALWAYS // since 4.5 +// +// Until 5.2, it was a part of map-type-modifier. Since 6.0 the +// map-type-modifier has been split into individual modifiers. +struct OmpAlwaysModifier { + ENUM_CLASS(Value, Always) + WRAPPER_CLASS_BOILERPLATE(OmpAlwaysModifier, Value); +}; + // Ref: [5.2:252-254] // // chunk-modifier -> @@ -3767,17 +3780,29 @@ struct OmpChunkModifier { WRAPPER_CLASS_BOILERPLATE(OmpChunkModifier, Value); }; -// Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69] +// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158], +// [6.0:279-288] // -// 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; +// close-modifier -> +// CLOSE // since 5.0 +// +// Until 5.2, it was a part of map-type-modifier. Since 6.0 the +// map-type-modifier has been split into individual modifiers. +struct OmpCloseModifier { + ENUM_CLASS(Value, Close) + WRAPPER_CLASS_BOILERPLATE(OmpCloseModifier, Value); +}; + +// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158], +// [6.0:279-288] +// +// delete-modifier -> +// DELETE // since 6.0 +// +// Until 5.2, it was a part of map-type. +struct OmpDeleteModifier { + ENUM_CLASS(Value, Delete) + WRAPPER_CLASS_BOILERPLATE(OmpDeleteModifier, Value); }; // Ref: [4.5:169-170], [5.0:255-256], [5.1:288-289] @@ -3867,6 +3892,19 @@ struct OmpInteropType { WRAPPER_CLASS_BOILERPLATE(OmpInteropType, Value); }; +// 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: [5.0:47-49], [5.1:49-51], [5.2:67-69] // // iterator-modifier -> @@ -3901,21 +3939,28 @@ struct OmpMapper { WRAPPER_CLASS_BOILERPLATE(OmpMapper, Name); }; -// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158] +// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158], +// [6.0:279-288] // // map-type -> -// ALLOC | DELETE | FROM | RELEASE | TO | TOFROM // since 4.5 +// ALLOC | DELETE | RELEASE | // since 4.5, until 5.2 +// FROM | TO | TOFROM | // since 4.5 +// STORAGE // since 6.0 +// +// Since 6.0 DELETE is a separate delete-modifier. struct OmpMapType { - ENUM_CLASS(Value, Alloc, Delete, From, Release, To, Tofrom); + ENUM_CLASS(Value, Alloc, Delete, From, Release, Storage, To, Tofrom); WRAPPER_CLASS_BOILERPLATE(OmpMapType, Value); }; // Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158] // // map-type-modifier -> -// ALWAYS | // since 4.5 -// CLOSE | // since 5.0 -// PRESENT // since 5.1 +// ALWAYS | // since 4.5, until 5.2 +// CLOSE | // since 5.0, until 5.2 +// PRESENT // since 5.1, until 5.2 +// Since 6.0 the map-type-modifier has been split into individual modifiers. +// struct OmpMapTypeModifier { ENUM_CLASS(Value, Always, Close, Present, Ompx_Hold) WRAPPER_CLASS_BOILERPLATE(OmpMapTypeModifier, Value); @@ -3954,6 +3999,19 @@ struct OmpPrescriptiveness { WRAPPER_CLASS_BOILERPLATE(OmpPrescriptiveness, Value); }; +// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158], +// [6.0:279-288] +// +// present-modifier -> +// PRESENT // since 5.1 +// +// Until 5.2, it was a part of map-type-modifier. Since 6.0 the +// map-type-modifier has been split into individual modifiers. +struct OmpPresentModifier { + ENUM_CLASS(Value, Present) + WRAPPER_CLASS_BOILERPLATE(OmpPresentModifier, Value); +}; + // Ref: [5.0:300-302], [5.1:332-334], [5.2:134-137] // // reduction-modifier -> @@ -3963,6 +4021,26 @@ struct OmpReductionModifier { WRAPPER_CLASS_BOILERPLATE(OmpReductionModifier, Value); }; +// Ref: [6.0:279-288] +// +// ref-modifier -> +// REF_PTEE | REF_PTR | REF_PTR_PTEE // since 6.0 +// +struct OmpRefModifier { + ENUM_CLASS(Value, Ref_Ptee, Ref_Ptr, Ref_Ptr_Ptee) + WRAPPER_CLASS_BOILERPLATE(OmpRefModifier, Value); +}; + +// Ref: [6.0:279-288] +// +// self-modifier -> +// SELF // since 6.0 +// +struct OmpSelfModifier { + ENUM_CLASS(Value, Self) + WRAPPER_CLASS_BOILERPLATE(OmpSelfModifier, Value); +}; + // Ref: [5.2:117-120] // // step-complex-modifier -> @@ -4001,6 +4079,19 @@ struct OmpVariableCategory { WRAPPER_CLASS_BOILERPLATE(OmpVariableCategory, Value); }; +// Extension: +// https://openmp.llvm.org//openacc/OpenMPExtensions.html#ompx-hold +// +// ompx-hold-modifier -> +// OMPX_HOLD // since 4.5 +// +// Until 5.2, it was a part of map-type-modifier. Since 6.0 the +// map-type-modifier has been split into individual modifiers. +struct OmpxHoldModifier { + ENUM_CLASS(Value, Ompx_Hold) + WRAPPER_CLASS_BOILERPLATE(OmpxHoldModifier, Value); +}; + // context-selector using OmpContextSelector = traits::OmpContextSelectorSpecification; } // namespace modifier @@ -4376,13 +4467,25 @@ struct OmpLinearClause { // map-clause -> // MAP([modifier...:] locator-list) // since 4.5 // modifier -> -// map-type-modifier | // since 4.5 +// map-type-modifier [replaced] | // since 4.5, until 5.2 +// always-modifier | // since 6.0 +// close-modifier | // since 6.0 +// delete-modifier | // since 6.0 +// present-modifier | // since 6.0 +// ref-modifier | // since 6.0 +// self-modifier | // since 6.0 // mapper | // since 5.0 // iterator | // since 5.1 // map-type // since 4.5 +// ompx-hold-modifier | // since 6.0 +// +// Since 6.0 the map-type-modifier has been split into individual modifiers, +// and delete-modifier has been split from map-type. struct OmpMapClause { TUPLE_CLASS_BOILERPLATE(OmpMapClause); - MODIFIER_BOILERPLATE(OmpMapTypeModifier, OmpMapper, OmpIterator, OmpMapType); + MODIFIER_BOILERPLATE(OmpAlwaysModifier, OmpCloseModifier, OmpDeleteModifier, + OmpMapTypeModifier, OmpPresentModifier, OmpRefModifier, OmpSelfModifier, + OmpMapper, OmpIterator, OmpMapType, OmpxHoldModifier); std::tuple t; }; diff --git a/flang/include/flang/Runtime/extensions.h b/flang/include/flang/Runtime/extensions.h index 06ae7f35d9b5b..b350204714431 100644 --- a/flang/include/flang/Runtime/extensions.h +++ b/flang/include/flang/Runtime/extensions.h @@ -12,14 +12,12 @@ #ifndef FORTRAN_RUNTIME_EXTENSIONS_H_ #define FORTRAN_RUNTIME_EXTENSIONS_H_ -#include "flang/Runtime/entry-names.h" - -#define FORTRAN_PROCEDURE_NAME(name) name##_ - #include "flang/Runtime/entry-names.h" #include #include +#define FORTRAN_PROCEDURE_NAME(name) name##_ + #ifdef _WIN32 // UID and GID don't exist on Windows, these exist to avoid errors. typedef std::uint32_t uid_t; @@ -89,5 +87,8 @@ int FORTRAN_PROCEDURE_NAME(ierrno)(); // GNU extension subroutine PERROR(STRING) void RTNAME(Perror)(const char *str); +// MCLOCK -- returns accumulated time in ticks +int FORTRAN_PROCEDURE_NAME(mclock)(); + } // extern "C" #endif // FORTRAN_RUNTIME_EXTENSIONS_H_ diff --git a/flang/include/flang/Runtime/pointer.h b/flang/include/flang/Runtime/pointer.h index 83472ee59d2ab..6787ef3ece232 100644 --- a/flang/include/flang/Runtime/pointer.h +++ b/flang/include/flang/Runtime/pointer.h @@ -59,9 +59,14 @@ void RTDECL(PointerAssociateLowerBounds)( // Associates a pointer with a target with bounds remapping. The target must be // simply contiguous &/or of rank 1. The bounds constitute a [2,newRank] // integer array whose columns are [lower bound, upper bound] on each dimension. +// Use the Monomorphic form if the pointer's type shouldn't change and +// the target is polymorphic. void RTDECL(PointerAssociateRemapping)(Descriptor &, const Descriptor &target, const Descriptor &bounds, const char *sourceFile = nullptr, int sourceLine = 0); +void RTDECL(PointerAssociateRemappingMonomorphic)(Descriptor &, + const Descriptor &target, const Descriptor &bounds, + const char *sourceFile = nullptr, int sourceLine = 0); // Data pointer allocation and deallocation diff --git a/flang/include/flang/Semantics/openmp-modifiers.h b/flang/include/flang/Semantics/openmp-modifiers.h index 4fbd80f989e72..a9fe911ef8807 100644 --- a/flang/include/flang/Semantics/openmp-modifiers.h +++ b/flang/include/flang/Semantics/openmp-modifiers.h @@ -71,8 +71,11 @@ DECLARE_DESCRIPTOR(parser::OmpAlignment); DECLARE_DESCRIPTOR(parser::OmpAlignModifier); DECLARE_DESCRIPTOR(parser::OmpAllocatorComplexModifier); DECLARE_DESCRIPTOR(parser::OmpAllocatorSimpleModifier); +DECLARE_DESCRIPTOR(parser::OmpAlwaysModifier); DECLARE_DESCRIPTOR(parser::OmpChunkModifier); +DECLARE_DESCRIPTOR(parser::OmpCloseModifier); DECLARE_DESCRIPTOR(parser::OmpContextSelector); +DECLARE_DESCRIPTOR(parser::OmpDeleteModifier); DECLARE_DESCRIPTOR(parser::OmpDependenceType); DECLARE_DESCRIPTOR(parser::OmpDeviceModifier); DECLARE_DESCRIPTOR(parser::OmpDirectiveNameModifier); @@ -88,12 +91,16 @@ DECLARE_DESCRIPTOR(parser::OmpMapTypeModifier); DECLARE_DESCRIPTOR(parser::OmpOrderModifier); DECLARE_DESCRIPTOR(parser::OmpOrderingModifier); DECLARE_DESCRIPTOR(parser::OmpPrescriptiveness); +DECLARE_DESCRIPTOR(parser::OmpPresentModifier); DECLARE_DESCRIPTOR(parser::OmpReductionIdentifier); DECLARE_DESCRIPTOR(parser::OmpReductionModifier); +DECLARE_DESCRIPTOR(parser::OmpRefModifier); +DECLARE_DESCRIPTOR(parser::OmpSelfModifier); DECLARE_DESCRIPTOR(parser::OmpStepComplexModifier); DECLARE_DESCRIPTOR(parser::OmpStepSimpleModifier); DECLARE_DESCRIPTOR(parser::OmpTaskDependenceType); DECLARE_DESCRIPTOR(parser::OmpVariableCategory); +DECLARE_DESCRIPTOR(parser::OmpxHoldModifier); #undef DECLARE_DESCRIPTOR diff --git a/flang/include/flang/Semantics/runtime-type-info.h b/flang/include/flang/Semantics/runtime-type-info.h index 6c5a061d1c1a2..94e8293b14643 100644 --- a/flang/include/flang/Semantics/runtime-type-info.h +++ b/flang/include/flang/Semantics/runtime-type-info.h @@ -52,10 +52,15 @@ constexpr char procCompName[]{"proc"}; SymbolVector CollectBindings(const Scope &dtScope); +enum NonTbpDefinedIoFlags { + IsDtvArgPolymorphic = 1 << 0, + DefinedIoInteger8 = 1 << 1, +}; + struct NonTbpDefinedIo { const Symbol *subroutine; common::DefinedIo definedIo; - bool isDtvArgPolymorphic; + std::uint8_t flags; }; std::multimap diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h index b319e2c7e5e74..5bde9f39ca0b0 100644 --- a/flang/include/flang/Semantics/symbol.h +++ b/flang/include/flang/Semantics/symbol.h @@ -812,9 +812,8 @@ class Symbol { // OpenMP data-sharing attribute OmpShared, OmpPrivate, OmpLinear, OmpFirstPrivate, OmpLastPrivate, // OpenMP data-mapping attribute - OmpMapTo, OmpMapFrom, OmpMapToFrom, OmpMapAlloc, OmpMapRelease, - OmpMapDelete, OmpUseDevicePtr, OmpUseDeviceAddr, OmpIsDevicePtr, - OmpHasDeviceAddr, + OmpMapTo, OmpMapFrom, OmpMapToFrom, OmpMapStorage, OmpMapDelete, + OmpUseDevicePtr, OmpUseDeviceAddr, OmpIsDevicePtr, OmpHasDeviceAddr, // OpenMP data-copying attribute OmpCopyIn, OmpCopyPrivate, // OpenMP miscellaneous flags diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp index 4773e136c41cb..d44239b41fa20 100644 --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -428,6 +428,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{ {"conjg", {{"z", SameComplex}}, SameComplex}, {"cos", {{"x", SameFloating}}, SameFloating}, {"cosd", {{"x", SameFloating}}, SameFloating}, + {"cospi", {{"x", SameFloating}}, SameFloating}, {"cosh", {{"x", SameFloating}}, SameFloating}, {"coshape", {{"coarray", AnyData, Rank::coarray}, SizeDefaultKIND}, KINDInt, Rank::vector, IntrinsicClass::inquiryFunction}, @@ -956,6 +957,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{ {"sin", {{"x", SameFloating}}, SameFloating}, {"sind", {{"x", SameFloating}}, SameFloating}, {"sinh", {{"x", SameFloating}}, SameFloating}, + {"sinpi", {{"x", SameFloating}}, SameFloating}, {"size", {{"array", AnyData, Rank::arrayOrAssumedRank}, OptionalDIM, // unless array is assumed-size diff --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp index 2429e07e5b8c4..58901c6000380 100644 --- a/flang/lib/Frontend/FrontendAction.cpp +++ b/flang/lib/Frontend/FrontendAction.cpp @@ -230,15 +230,14 @@ bool FrontendAction::reportFatalErrors(const char (&message)[N]) { const common::LanguageFeatureControl &features{ instance->getInvocation().getFortranOpts().features}; const size_t maxErrors{instance->getInvocation().getMaxErrors()}; - if (!instance->getParsing().messages().empty() && - (instance->getInvocation().getWarnAsErr() || - instance->getParsing().messages().AnyFatalError())) { + const bool warningsAreErrors{instance->getInvocation().getWarnAsErr()}; + if (instance->getParsing().messages().AnyFatalError(warningsAreErrors)) { const unsigned diagID = instance->getDiagnostics().getCustomDiagID( clang::DiagnosticsEngine::Error, message); instance->getDiagnostics().Report(diagID) << getCurrentFileOrBufferName(); instance->getParsing().messages().Emit( llvm::errs(), instance->getAllCookedSources(), - /*echoSourceLines=*/true, &features, maxErrors); + /*echoSourceLines=*/true, &features, maxErrors, warningsAreErrors); return true; } if (instance->getParsing().parseTree().has_value() && @@ -249,7 +248,7 @@ bool FrontendAction::reportFatalErrors(const char (&message)[N]) { instance->getDiagnostics().Report(diagID) << getCurrentFileOrBufferName(); instance->getParsing().messages().Emit( llvm::errs(), instance->getAllCookedSources(), - /*echoSourceLine=*/true, &features, maxErrors); + /*echoSourceLine=*/true, &features, maxErrors, warningsAreErrors); instance->getParsing().EmitMessage( llvm::errs(), instance->getParsing().finalRestingPlace(), "parser FAIL (final position)", "error: ", llvm::raw_ostream::RED); diff --git a/flang/lib/Lower/Allocatable.cpp b/flang/lib/Lower/Allocatable.cpp index 5536bfe8d63ca..15cd9770b35ba 100644 --- a/flang/lib/Lower/Allocatable.cpp +++ b/flang/lib/Lower/Allocatable.cpp @@ -78,8 +78,8 @@ struct ErrorManager { statExpr && errMsgExpr ? builder.createBox(loc, converter.genExprAddr(loc, errMsgExpr, stmtCtx)) - : builder.create( - loc, + : fir::AbsentOp::create( + builder, loc, fir::BoxType::get(mlir::NoneType::get(builder.getContext()))); sourceFile = fir::factory::locationToFilename(builder, loc); sourceLine = fir::factory::locationToLineNo(builder, loc, @@ -92,10 +92,10 @@ struct ErrorManager { if (statValue) { mlir::Value zero = builder.createIntegerConstant(loc, statValue.getType(), 0); - auto cmp = builder.create( - loc, mlir::arith::CmpIPredicate::eq, statValue, zero); - auto ifOp = builder.create(loc, cmp, - /*withElseRegion=*/false); + auto cmp = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, statValue, zero); + auto ifOp = fir::IfOp::create(builder, loc, cmp, + /*withElseRegion=*/false); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); } } @@ -106,7 +106,7 @@ struct ErrorManager { assert(stat && "missing stat value"); mlir::Value castStat = builder.createConvert( loc, fir::dyn_cast_ptrEleTy(statAddr.getType()), stat); - builder.create(loc, castStat, statAddr); + fir::StoreOp::create(builder, loc, castStat, statAddr); statValue = stat; } } @@ -141,7 +141,7 @@ static void genRuntimeSetBounds(fir::FirOpBuilder &builder, mlir::Location loc, const auto args = fir::runtime::createArguments( builder, loc, callee.getFunctionType(), box.getAddr(), dimIndex, lowerBound, upperBound); - builder.create(loc, callee, args); + fir::CallOp::create(builder, loc, callee, args); } /// Generate runtime call to set the lengths of a character allocatable or @@ -171,7 +171,7 @@ static void genRuntimeInitCharacter(fir::FirOpBuilder &builder, args.push_back(builder.createIntegerConstant(loc, inputTypes[4], corank)); const auto convertedArgs = fir::runtime::createArguments( builder, loc, callee.getFunctionType(), args); - builder.create(loc, callee, convertedArgs); + fir::CallOp::create(builder, loc, callee, convertedArgs); } /// Generate a sequence of runtime calls to allocate memory. @@ -194,7 +194,7 @@ static mlir::Value genRuntimeAllocate(fir::FirOpBuilder &builder, args.push_back(errorManager.sourceLine); const auto convertedArgs = fir::runtime::createArguments( builder, loc, callee.getFunctionType(), args); - return builder.create(loc, callee, convertedArgs).getResult(0); + return fir::CallOp::create(builder, loc, callee, convertedArgs).getResult(0); } /// Generate a sequence of runtime calls to allocate memory and assign with the @@ -214,7 +214,7 @@ static mlir::Value genRuntimeAllocateSource(fir::FirOpBuilder &builder, builder, loc, callee.getFunctionType(), box.getAddr(), fir::getBase(source), errorManager.hasStat, errorManager.errMsgAddr, errorManager.sourceFile, errorManager.sourceLine); - return builder.create(loc, callee, args).getResult(0); + return fir::CallOp::create(builder, loc, callee, args).getResult(0); } /// Generate runtime call to apply mold to the descriptor. @@ -233,7 +233,7 @@ static void genRuntimeAllocateApplyMold(fir::FirOpBuilder &builder, fir::factory::getMutableIRBox(builder, loc, box), fir::getBase(mold), builder.createIntegerConstant( loc, callee.getFunctionType().getInputs()[2], rank)); - builder.create(loc, callee, args); + fir::CallOp::create(builder, loc, callee, args); } /// Generate a runtime call to deallocate memory. @@ -270,7 +270,7 @@ static mlir::Value genRuntimeDeallocate(fir::FirOpBuilder &builder, errorManager.hasStat, errorManager.errMsgAddr, errorManager.sourceFile, errorManager.sourceLine); } - return builder.create(loc, callee, operands).getResult(0); + return fir::CallOp::create(builder, loc, callee, operands).getResult(0); } //===----------------------------------------------------------------------===// @@ -433,9 +433,9 @@ class AllocateStmtHelper { loc, Fortran::semantics::GetExpr(std::get<1>(shapeSpec.t)), stmtCtx)); ub = builder.createConvert(loc, idxTy, ub); if (lb) { - mlir::Value diff = builder.create(loc, ub, lb); + mlir::Value diff = mlir::arith::SubIOp::create(builder, loc, ub, lb); extents.emplace_back( - builder.create(loc, diff, one)); + mlir::arith::AddIOp::create(builder, loc, diff, one)); } else { extents.emplace_back(ub); } @@ -461,7 +461,7 @@ class AllocateStmtHelper { mlir::Value falseValue = builder.createBool(loc, false); mlir::Value falseConv = builder.createConvert( loc, fir::unwrapRefType(pinned.getType()), falseValue); - builder.create(loc, falseConv, pinned); + fir::StoreOp::create(builder, loc, falseConv, pinned); } void genSimpleAllocation(const Allocation &alloc, @@ -557,7 +557,7 @@ class AllocateStmtHelper { mlir::Value nullPointer = fir::factory::createUnallocatedBox( builder, loc, box.getBoxTy(), box.nonDeferredLenParams(), /*typeSourceBox=*/{}, allocatorIdx); - builder.create(loc, nullPointer, box.getAddr()); + fir::StoreOp::create(builder, loc, nullPointer, box.getAddr()); } else { assert(box.isAllocatable() && "must be an allocatable"); // For allocatables, sync the MutableBoxValue and descriptor before the @@ -597,13 +597,14 @@ class AllocateStmtHelper { assert(sourceBox && "source expression should be lowered to one box"); for (int i = 0; i < sourceExpr->Rank(); ++i) { auto dimVal = builder.createIntegerConstant(loc, idxTy, i); - auto dimInfo = builder.create( - loc, idxTy, idxTy, idxTy, sourceBox->getAddr(), dimVal); + auto dimInfo = fir::BoxDimsOp::create(builder, loc, idxTy, idxTy, idxTy, + sourceBox->getAddr(), dimVal); mlir::Value lb = fir::factory::readLowerBound(builder, loc, sourceExv, i, one); mlir::Value extent = dimInfo.getResult(1); - mlir::Value ub = builder.create( - loc, builder.create(loc, extent, lb), one); + mlir::Value ub = mlir::arith::SubIOp::create( + builder, loc, mlir::arith::AddIOp::create(builder, loc, extent, lb), + one); mlir::Value dimIndex = builder.createIntegerConstant(loc, i32Ty, i); genRuntimeSetBounds(builder, loc, box, dimIndex, lb, ub); } @@ -668,7 +669,7 @@ class AllocateStmtHelper { const auto args = fir::runtime::createArguments( builder, loc, callee.getFunctionType(), box.getAddr(), typeDescAddr, rankValue, corankValue); - builder.create(loc, callee, args); + fir::CallOp::create(builder, loc, callee, args); } /// Generate call to PointerNullifyIntrinsic or AllocatableInitIntrinsic to @@ -697,7 +698,7 @@ class AllocateStmtHelper { const auto args = fir::runtime::createArguments( builder, loc, callee.getFunctionType(), box.getAddr(), categoryValue, kindValue, rankValue, corankValue); - builder.create(loc, callee, args); + fir::CallOp::create(builder, loc, callee, args); } /// Generate call to the AllocatableInitDerived to set up the type descriptor @@ -909,8 +910,8 @@ void Fortran::lower::genDeallocateIfAllocated( .genThen([&]() { if (mlir::Type eleType = box.getEleTy(); mlir::isa(eleType) && box.isPolymorphic()) { - mlir::Value declaredTypeDesc = builder.create( - loc, mlir::TypeAttr::get(eleType)); + mlir::Value declaredTypeDesc = fir::TypeDescOp::create( + builder, loc, mlir::TypeAttr::get(eleType)); genDeallocateBox(converter, box, loc, sym, declaredTypeDesc); } else { genDeallocateBox(converter, box, loc, sym); @@ -1151,7 +1152,7 @@ mlir::Value Fortran::lower::getAssumedCharAllocatableOrPointerLen( // here). auto readLength = [&]() { fir::BoxValue boxLoad = - builder.create(loc, fir::getBase(box)).getResult(); + fir::LoadOp::create(builder, loc, fir::getBase(box)).getResult(); return fir::factory::readCharLen(builder, loc, boxLoad); }; if (Fortran::semantics::IsOptional(sym)) { @@ -1160,15 +1161,15 @@ mlir::Value Fortran::lower::getAssumedCharAllocatableOrPointerLen( // they are absents. According to 15.5.2.12 3 (9), it is illegal to // inquire the length of absent optional, even if non deferred, so // it's fine to use undefOp in this case. - auto isPresent = builder.create(loc, builder.getI1Type(), - fir::getBase(box)); + auto isPresent = fir::IsPresentOp::create(builder, loc, builder.getI1Type(), + fir::getBase(box)); mlir::Value len = builder.genIfOp(loc, {idxTy}, isPresent, true) .genThen( - [&]() { builder.create(loc, readLength()); }) + [&]() { fir::ResultOp::create(builder, loc, readLength()); }) .genElse([&]() { - auto undef = builder.create(loc, idxTy); - builder.create(loc, undef.getResult()); + auto undef = fir::UndefOp::create(builder, loc, idxTy); + fir::ResultOp::create(builder, loc, undef.getResult()); }) .getResults()[0]; return len; @@ -1183,5 +1184,5 @@ mlir::Value Fortran::lower::getTypeDescAddr( mlir::Type typeDesc = Fortran::lower::translateDerivedTypeToFIRType(converter, typeSpec); fir::FirOpBuilder &builder = converter.getFirOpBuilder(); - return builder.create(loc, mlir::TypeAttr::get(typeDesc)); + return fir::TypeDescOp::create(builder, loc, mlir::TypeAttr::get(typeDesc)); } diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 33c1f1e7a3c3a..b94833d852b2e 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -333,11 +333,12 @@ class TypeInfoConverter { if (details.numPrivatesNotOverridden() > 0) tbpName += "."s + std::to_string(details.numPrivatesNotOverridden()); std::string bindingName = converter.mangleName(details.symbol()); - builder.create( - info.loc, mlir::StringAttr::get(builder.getContext(), tbpName), + fir::DTEntryOp::create( + builder, info.loc, + mlir::StringAttr::get(builder.getContext(), tbpName), mlir::SymbolRefAttr::get(builder.getContext(), bindingName)); } - builder.create(info.loc); + fir::FirEndOp::create(builder, info.loc); } // Gather info about components that is not reflected in fir.type and may be // needed later: component initial values and array component non default @@ -360,11 +361,11 @@ class TypeInfoConverter { componentInfo = builder.createBlock(&dt.getComponentInfo()); auto compName = mlir::StringAttr::get(builder.getContext(), toStringRef(component.name())); - builder.create(info.loc, compName, lbs, init_val); + fir::DTComponentOp::create(builder, info.loc, compName, lbs, init_val); } } if (componentInfo) - builder.create(info.loc); + fir::FirEndOp::create(builder, info.loc); builder.restoreInsertionPoint(insertPointIfCreated); } @@ -810,11 +811,11 @@ class FirConverter : public Fortran::lower::AbstractConverter { fir::ExtendedValue read = fir::factory::genMutableBoxRead( *builder, loc, box, /*mayBePolymorphic=*/false); if (auto read_arr_box = read.getBoxOf()) { - fir::factory::genInlinedAllocation( - *builder, loc, *new_box, read_arr_box->getLBounds(), - read_arr_box->getExtents(), - /*lenParams=*/std::nullopt, name, - /*mustBeHeap=*/true); + fir::factory::genInlinedAllocation(*builder, loc, *new_box, + read_arr_box->getLBounds(), + read_arr_box->getExtents(), + /*lenParams=*/{}, name, + /*mustBeHeap=*/true); } else if (auto read_char_arr_box = read.getBoxOf()) { fir::factory::genInlinedAllocation( @@ -825,8 +826,8 @@ class FirConverter : public Fortran::lower::AbstractConverter { } else if (auto read_char_box = read.getBoxOf()) { fir::factory::genInlinedAllocation(*builder, loc, *new_box, - /*lbounds=*/std::nullopt, - /*extents=*/std::nullopt, + /*lbounds=*/{}, + /*extents=*/{}, read_char_box->getLen(), name, /*mustBeHeap=*/true); } else { @@ -1466,8 +1467,9 @@ class FirConverter : public Fortran::lower::AbstractConverter { assert(falseTarget && "missing conditional branch false block"); mlir::Location loc = toLocation(); mlir::Value bcc = builder->createConvert(loc, builder->getI1Type(), cond); - builder->create(loc, bcc, trueTarget, std::nullopt, - falseTarget, std::nullopt); + builder->create(loc, bcc, trueTarget, + mlir::ValueRange{}, falseTarget, + mlir::ValueRange{}); } void genConditionalBranch(mlir::Value cond, Fortran::lower::pft::Evaluation *trueTarget, @@ -2556,8 +2558,8 @@ class FirConverter : public Fortran::lower::AbstractConverter { builder->setInsertionPointToEnd(loopWrapperOp.getBody()); auto loopOp = builder->create( loc, nestLBs, nestUBs, nestSts, /*loopAnnotation=*/nullptr, - /*local_vars=*/std::nullopt, - /*local_syms=*/nullptr, /*reduce_vars=*/std::nullopt, + /*local_vars=*/mlir::ValueRange{}, + /*local_syms=*/nullptr, /*reduce_vars=*/mlir::ValueRange{}, /*reduce_byref=*/nullptr, /*reduce_syms=*/nullptr, /*reduce_attrs=*/nullptr); @@ -3810,9 +3812,9 @@ class FirConverter : public Fortran::lower::AbstractConverter { mlir::Block *selectCaseBlock = insertBlock(blockList[0]); mlir::Block *assumedSizeBlock = rankStarBlock ? rankStarBlock : defaultBlock; - builder->create(loc, isAssumedSize, - assumedSizeBlock, std::nullopt, - selectCaseBlock, std::nullopt); + builder->create( + loc, isAssumedSize, assumedSizeBlock, mlir::ValueRange{}, + selectCaseBlock, mlir::ValueRange{}); startBlock(selectCaseBlock); } // Create fir.select_case for the other rank cases. @@ -4590,8 +4592,7 @@ class FirConverter : public Fortran::lower::AbstractConverter { // the static type of the LHS. if (Fortran::evaluate::UnwrapExpr( assign.rhs)) - return fir::factory::createUnallocatedBox(*builder, loc, lhsBoxType, - std::nullopt); + return fir::factory::createUnallocatedBox(*builder, loc, lhsBoxType, {}); hlfir::Entity rhs = Fortran::lower::convertExprToHLFIR( loc, *this, assign.rhs, localSymbols, rhsContext); // Create pointer descriptor value from the RHS. @@ -4703,8 +4704,10 @@ class FirConverter : public Fortran::lower::AbstractConverter { mlir::Value lhs = lhsMutableBox.getAddr(); mlir::Value rhs = fir::getBase(genExprBox(loc, assign.rhs, stmtCtx)); mlir::Value boundsDesc = createBoundArray(lbounds, ubounds, loc); - Fortran::lower::genPointerAssociateRemapping(*builder, loc, lhs, rhs, - boundsDesc); + Fortran::lower::genPointerAssociateRemapping( + *builder, loc, lhs, rhs, boundsDesc, + lhsType && rhsType && !lhsType->IsPolymorphic() && + rhsType->IsPolymorphic()); return; } if (!lowerToHighLevelFIR() && explicitIterationSpace()) { @@ -4827,18 +4830,18 @@ class FirConverter : public Fortran::lower::AbstractConverter { base = convertOp.getValue(); // Special case if the rhs is a constant. if (matchPattern(base.getDefiningOp(), mlir::m_Constant())) { - builder.create(loc, base, lhsVal, shape, - transferKindAttr); + cuf::DataTransferOp::create(builder, loc, base, lhsVal, shape, + transferKindAttr); } else { auto associate = hlfir::genAssociateExpr( loc, builder, rhs, rhs.getType(), ".cuf_host_tmp"); - builder.create(loc, associate.getBase(), lhsVal, - shape, transferKindAttr); - builder.create(loc, associate); + cuf::DataTransferOp::create(builder, loc, associate.getBase(), lhsVal, + shape, transferKindAttr); + hlfir::EndAssociateOp::create(builder, loc, associate); } } else { - builder.create(loc, rhsVal, lhsVal, shape, - transferKindAttr); + cuf::DataTransferOp::create(builder, loc, rhsVal, lhsVal, shape, + transferKindAttr); } return; } @@ -4847,8 +4850,8 @@ class FirConverter : public Fortran::lower::AbstractConverter { if (!lhsIsDevice && rhsIsDevice) { auto transferKindAttr = cuf::DataTransferKindAttr::get( builder.getContext(), cuf::DataTransferKind::DeviceHost); - builder.create(loc, rhsVal, lhsVal, shape, - transferKindAttr); + cuf::DataTransferOp::create(builder, loc, rhsVal, lhsVal, shape, + transferKindAttr); return; } @@ -4857,8 +4860,8 @@ class FirConverter : public Fortran::lower::AbstractConverter { assert(rhs.isVariable() && "CUDA Fortran assignment rhs is not legal"); auto transferKindAttr = cuf::DataTransferKindAttr::get( builder.getContext(), cuf::DataTransferKind::DeviceDevice); - builder.create(loc, rhsVal, lhsVal, shape, - transferKindAttr); + cuf::DataTransferOp::create(builder, loc, rhsVal, lhsVal, shape, + transferKindAttr); return; } llvm_unreachable("Unhandled CUDA data transfer"); @@ -4904,8 +4907,9 @@ class FirConverter : public Fortran::lower::AbstractConverter { addSymbol(sym, hlfir::translateToExtendedValue(loc, builder, temp).first, /*forced=*/true); - builder.create( - loc, addr, temp, /*shape=*/mlir::Value{}, transferKindAttr); + cuf::DataTransferOp::create(builder, loc, addr, temp, + /*shape=*/mlir::Value{}, + transferKindAttr); ++nbDeviceResidentObject; } } @@ -4994,13 +4998,13 @@ class FirConverter : public Fortran::lower::AbstractConverter { if (isCUDATransfer && !hasCUDAImplicitTransfer) genCUDADataTransfer(builder, loc, assign, lhs, rhs); else - builder.create(loc, rhs, lhs, - isWholeAllocatableAssignment, - keepLhsLengthInAllocatableAssignment); + hlfir::AssignOp::create(builder, loc, rhs, lhs, + isWholeAllocatableAssignment, + keepLhsLengthInAllocatableAssignment); if (hasCUDAImplicitTransfer && !isInDeviceContext) { localSymbols.popScope(); for (mlir::Value temp : implicitTemps) - builder.create(loc, temp); + fir::FreeMemOp::create(builder, loc, temp); } return; } @@ -5008,13 +5012,13 @@ class FirConverter : public Fortran::lower::AbstractConverter { // left-hand side requires using an hlfir.region_assign in HLFIR. The // right-hand side and left-hand side must be evaluated inside the // hlfir.region_assign regions. - auto regionAssignOp = builder.create(loc); + auto regionAssignOp = hlfir::RegionAssignOp::create(builder, loc); // Lower RHS in its own region. builder.createBlock(®ionAssignOp.getRhsRegion()); Fortran::lower::StatementContext rhsContext; hlfir::Entity rhs = evaluateRhs(rhsContext); - auto rhsYieldOp = builder.create(loc, rhs); + auto rhsYieldOp = hlfir::YieldOp::create(builder, loc, rhs); Fortran::lower::genCleanUpInRegionIfAny( loc, builder, rhsYieldOp.getCleanup(), rhsContext); // Lower LHS in its own region. @@ -5023,7 +5027,7 @@ class FirConverter : public Fortran::lower::AbstractConverter { mlir::Value lhsYield = nullptr; if (!lhsHasVectorSubscripts) { hlfir::Entity lhs = evaluateLhs(lhsContext); - auto lhsYieldOp = builder.create(loc, lhs); + auto lhsYieldOp = hlfir::YieldOp::create(builder, loc, lhs); Fortran::lower::genCleanUpInRegionIfAny( loc, builder, lhsYieldOp.getCleanup(), lhsContext); lhsYield = lhs; @@ -5052,7 +5056,7 @@ class FirConverter : public Fortran::lower::AbstractConverter { builder.createBlock(®ionAssignOp.getUserDefinedAssignment(), mlir::Region::iterator{}, {rhsType, lhsType}, {loc, loc}); - auto end = builder.create(loc); + auto end = fir::FirEndOp::create(builder, loc); builder.setInsertionPoint(end); hlfir::Entity lhsBlockArg{regionAssignOp.getUserAssignmentLhs()}; hlfir::Entity rhsBlockArg{regionAssignOp.getUserAssignmentRhs()}; @@ -5199,7 +5203,7 @@ class FirConverter : public Fortran::lower::AbstractConverter { "LEN parameters"); lhsRealloc = fir::factory::genReallocIfNeeded( *builder, loc, *lhsMutableBox, - /*shape=*/std::nullopt, lengthParams); + /*shape=*/{}, lengthParams); return lhsRealloc->newValue; } return genExprAddr(assign.lhs, stmtCtx); @@ -5271,7 +5275,7 @@ class FirConverter : public Fortran::lower::AbstractConverter { if (lhsIsWholeAllocatable) { assert(lhsRealloc.has_value()); fir::factory::finalizeRealloc(*builder, loc, *lhsMutableBox, - /*lbounds=*/std::nullopt, + /*lbounds=*/{}, /*takeLboundsIfRealloc=*/false, *lhsRealloc); } @@ -6059,8 +6063,7 @@ class FirConverter : public Fortran::lower::AbstractConverter { mlir::func::FuncOp func = fir::FirOpBuilder::createFunction( mlir::UnknownLoc::get(context), getModuleOp(), fir::NameUniquer::doGenerated("Sham"), - mlir::FunctionType::get(context, std::nullopt, std::nullopt), - symbolTable); + mlir::FunctionType::get(context, {}, {}), symbolTable); func.addEntryBlock(); CHECK(!builder && "Expected builder to be uninitialized"); builder = new fir::FirOpBuilder(func, bridge.getKindMap(), symbolTable); diff --git a/flang/lib/Lower/ConvertArrayConstructor.cpp b/flang/lib/Lower/ConvertArrayConstructor.cpp index 7e2142693eac5..55c4b45554f78 100644 --- a/flang/lib/Lower/ConvertArrayConstructor.cpp +++ b/flang/lib/Lower/ConvertArrayConstructor.cpp @@ -137,9 +137,9 @@ class InlinedTempStrategyImpl : public StrategyBase, mlir::Value stride) { if constexpr (!hasLoops) fir::emitFatalError(loc, "array constructor lowering is inconsistent"); - auto loop = builder.create(loc, lower, upper, stride, - /*unordered=*/false, - /*finalCount=*/false); + auto loop = fir::DoLoopOp::create(builder, loc, lower, upper, stride, + /*unordered=*/false, + /*finalCount=*/false); builder.setInsertionPointToStart(loop.getBody()); return loop.getInductionVar(); } @@ -213,15 +213,15 @@ class AsElementalStrategy : public StrategyBase { assert(!elementalOp && "expected only one implied-do"); mlir::Value one = builder.createIntegerConstant(loc, builder.getIndexType(), 1); - elementalOp = builder.create( - loc, exprType, shape, - /*mold=*/nullptr, lengthParams, /*isUnordered=*/true); + elementalOp = hlfir::ElementalOp::create(builder, loc, exprType, shape, + /*mold=*/nullptr, lengthParams, + /*isUnordered=*/true); builder.setInsertionPointToStart(elementalOp.getBody()); // implied-do-index = lower+((i-1)*stride) - mlir::Value diff = builder.create( - loc, elementalOp.getIndices()[0], one); - mlir::Value mul = builder.create(loc, diff, stride); - mlir::Value add = builder.create(loc, lower, mul); + mlir::Value diff = mlir::arith::SubIOp::create( + builder, loc, elementalOp.getIndices()[0], one); + mlir::Value mul = mlir::arith::MulIOp::create(builder, loc, diff, stride); + mlir::Value add = mlir::arith::AddIOp::create(builder, loc, lower, mul); return add; } @@ -260,7 +260,7 @@ class AsElementalStrategy : public StrategyBase { if (destroyOp) destroyOp->erase(); - builder.create(loc, elementResult); + hlfir::YieldElementOp::create(builder, loc, elementResult); } // Override the default, because the context scope must be popped in @@ -315,8 +315,8 @@ class RuntimeTempStrategy : public StrategyBase { mlir::Value tempStorage = builder.createHeapTemporary( loc, declaredType, tempName, extents, lengths); mlir::Value shape = builder.genShape(loc, extents); - declare = builder.create( - loc, tempStorage, tempName, shape, lengths, + declare = hlfir::DeclareOp::create( + builder, loc, tempStorage, tempName, shape, lengths, /*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{}); initialBoxValue = builder.createBox(loc, boxType, declare->getOriginalBase(), shape, @@ -347,7 +347,7 @@ class RuntimeTempStrategy : public StrategyBase { /*slice=*/mlir::Value{}, emboxLengths, /*tdesc=*/{}); } - builder.create(loc, initialBoxValue, allocatableTemp); + fir::StoreOp::create(builder, loc, initialBoxValue, allocatableTemp); arrayConstructorVector = fir::runtime::genInitArrayConstructorVector( loc, builder, allocatableTemp, builder.createBool(loc, missingLengthParameters)); @@ -369,7 +369,7 @@ class RuntimeTempStrategy : public StrategyBase { loc, builder, value, arrayConstructorElementType); mlir::Value addr = fir::getBase(addrExv); if (mlir::isa(addr.getType())) - addr = builder.create(loc, addr); + addr = fir::BoxAddrOp::create(builder, loc, addr); fir::runtime::genPushArrayConstructorSimpleScalar( loc, builder, arrayConstructorVector, addr); if (cleanUp) @@ -389,9 +389,9 @@ class RuntimeTempStrategy : public StrategyBase { mlir::Value startImpliedDo(mlir::Location loc, fir::FirOpBuilder &builder, mlir::Value lower, mlir::Value upper, mlir::Value stride) { - auto loop = builder.create(loc, lower, upper, stride, - /*unordered=*/false, - /*finalCount=*/false); + auto loop = fir::DoLoopOp::create(builder, loc, lower, upper, stride, + /*unordered=*/false, + /*finalCount=*/false); builder.setInsertionPointToStart(loop.getBody()); return loop.getInductionVar(); } @@ -409,7 +409,7 @@ class RuntimeTempStrategy : public StrategyBase { else temp = hlfir::derefPointersAndAllocatables( loc, builder, hlfir::Entity{allocatableTemp}); - auto hlfirExpr = builder.create(loc, temp, mustFree); + auto hlfirExpr = hlfir::AsExprOp::create(builder, loc, temp, mustFree); return hlfir::Entity{hlfirExpr}; } diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp index 6ed15df0de754..8c3648bcb0f35 100644 --- a/flang/lib/Lower/ConvertCall.cpp +++ b/flang/lib/Lower/ConvertCall.cpp @@ -85,7 +85,7 @@ static mlir::Value genRecordCPtrValueArg(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value rec, mlir::Type ty) { mlir::Value cAddr = fir::factory::genCPtrOrCFunptrAddr(builder, loc, rec, ty); - mlir::Value cVal = builder.create(loc, cAddr); + mlir::Value cVal = fir::LoadOp::create(builder, loc, cAddr); return builder.createConvert(loc, cAddr.getType(), cVal); } @@ -159,8 +159,8 @@ static mlir::Value readDim3Value(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type refI32Ty = fir::ReferenceType::get(i32Ty); llvm::SmallVector lenParams; - mlir::Value designate = builder.create( - loc, refI32Ty, dim3Addr, /*component=*/comp, + mlir::Value designate = hlfir::DesignateOp::create( + builder, loc, refI32Ty, dim3Addr, /*component=*/comp, /*componentShape=*/mlir::Value{}, hlfir::DesignateOp::Subscripts{}, /*substring=*/mlir::ValueRange{}, /*complexPartAttr=*/std::nullopt, mlir::Value{}, lenParams); @@ -229,8 +229,8 @@ static mlir::Value remapActualToDummyDescriptor( if (fir::isPolymorphicType(dummyBoxType)) mold = explicitArgument; mlir::Value remapped = - builder.create(loc, dummyBoxType, baseAddr, shape, - /*slice=*/mlir::Value{}, lengths, mold); + fir::EmboxOp::create(builder, loc, dummyBoxType, baseAddr, shape, + /*slice=*/mlir::Value{}, lengths, mold); if (mapSymbols) symMap.popScope(); return remapped; @@ -273,12 +273,12 @@ static void remapActualToDummyDescriptors( mlir::Value newBox = remapActualToDummyDescriptor( loc, converter, symMap, argLambdaCapture, caller, isBindcCall); - builder.create(loc, newBox); + fir::ResultOp::create(builder, loc, newBox); }) .genElse([&]() { mlir::Value absent = - builder.create(loc, dummyType); - builder.create(loc, absent); + fir::AbsentOp::create(builder, loc, dummyType); + fir::ResultOp::create(builder, loc, absent); }) .getResults()[0]; caller.placeInput(arg, remapped); @@ -381,8 +381,8 @@ Fortran::lower::genCallOpAndResult( if (isExprCall) { mlir::Type exprType = hlfir::getExprType(type); - evaluateInMemory = builder.create( - loc, exprType, arrayResultShape, resultLengths); + evaluateInMemory = hlfir::EvaluateInMemoryOp::create( + builder, loc, exprType, arrayResultShape, resultLengths); builder.setInsertionPointToStart(&evaluateInMemory.getBody().front()); return toExtendedValue(loc, evaluateInMemory.getMemory(), extents, lengths); @@ -454,7 +454,7 @@ Fortran::lower::genCallOpAndResult( if (!addHostAssociations && mustCastFuncOpToCopeWithImplicitInterfaceMismatch( loc, converter, callSiteType, funcOpType)) - funcPointer = builder.create(loc, funcOpType, symbolAttr); + funcPointer = fir::AddrOfOp::create(builder, loc, funcOpType, symbolAttr); else funcSymbolAttr = symbolAttr; @@ -482,7 +482,7 @@ Fortran::lower::genCallOpAndResult( if (funcPointer) { operands.push_back( mlir::isa(funcPointer.getType()) - ? builder.create(loc, funcType, funcPointer) + ? fir::BoxAddrOp::create(builder, loc, funcType, funcPointer) : builder.createConvert(loc, funcType, funcPointer)); } @@ -496,14 +496,13 @@ Fortran::lower::genCallOpAndResult( auto *context = builder.getContext(); if (mlir::isa(snd) && mlir::isa(fst.getType())) { - auto funcTy = - mlir::FunctionType::get(context, std::nullopt, std::nullopt); + auto funcTy = mlir::FunctionType::get(context, {}, {}); auto boxProcTy = builder.getBoxProcType(funcTy); if (mlir::Value host = argumentHostAssocs(converter, fst)) { - cast = builder.create( - loc, boxProcTy, llvm::ArrayRef{fst, host}); + cast = fir::EmboxProcOp::create(builder, loc, boxProcTy, + llvm::ArrayRef{fst, host}); } else { - cast = builder.create(loc, boxProcTy, fst); + cast = fir::EmboxProcOp::create(builder, loc, boxProcTy, fst); } } else { mlir::Type fromTy = fir::unwrapRefType(fst.getType()); @@ -614,10 +613,10 @@ Fortran::lower::genCallOpAndResult( stream = fir::getBase(converter.genExprAddr( caller.getCallDescription().chevrons()[3], stmtCtx)); - builder.create( - loc, funcType.getResults(), funcSymbolAttr, grid_x, grid_y, grid_z, - block_x, block_y, block_z, bytes, stream, operands, - /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr); + cuf::KernelLaunchOp::create(builder, loc, funcType.getResults(), + funcSymbolAttr, grid_x, grid_y, grid_z, block_x, + block_y, block_z, bytes, stream, operands, + /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr); callNumResults = 0; } else if (caller.requireDispatchCall()) { // Procedure call requiring a dynamic dispatch. Call is created with @@ -641,8 +640,8 @@ Fortran::lower::genCallOpAndResult( // passed object because interface mismatch issues may have inserted a // cast to the operand with a different declared type, which would break // later type bound call resolution in the FIR to FIR pass. - dispatch = builder.create( - loc, funcType.getResults(), builder.getStringAttr(procName), + dispatch = fir::DispatchOp::create( + builder, loc, funcType.getResults(), builder.getStringAttr(procName), caller.getInputs()[*passArg], operands, builder.getI32IntegerAttr(*passArg), /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr, procAttrs); @@ -657,9 +656,9 @@ Fortran::lower::genCallOpAndResult( mlir::Value passObject = fir::getBase(dataRefValue); if (fir::isa_ref_type(passObject.getType())) - passObject = builder.create(loc, passObject); - dispatch = builder.create( - loc, funcType.getResults(), builder.getStringAttr(procName), + passObject = fir::LoadOp::create(builder, loc, passObject); + dispatch = fir::DispatchOp::create( + builder, loc, funcType.getResults(), builder.getStringAttr(procName), passObject, operands, nullptr, /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr, procAttrs); } @@ -668,8 +667,8 @@ Fortran::lower::genCallOpAndResult( callResult = dispatch.getResult(0); } else { // Standard procedure call with fir.call. - auto call = builder.create( - loc, funcType.getResults(), funcSymbolAttr, operands, + auto call = fir::CallOp::create( + builder, loc, funcType.getResults(), funcSymbolAttr, operands, /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr, procAttrs); callNumResults = call.getNumResults(); @@ -692,9 +691,9 @@ Fortran::lower::genCallOpAndResult( if (caller.mustSaveResult()) { assert(allocatedResult.has_value()); - builder.create(loc, callResult, - fir::getBase(*allocatedResult), - arrayResultShape, resultLengths); + fir::SaveResultOp::create(builder, loc, callResult, + fir::getBase(*allocatedResult), arrayResultShape, + resultLengths); } if (evaluateInMemory) { @@ -865,9 +864,9 @@ static hlfir::EntityWithAttributes genStmtFunctionRef( // The result must not be a variable. result = hlfir::loadTrivialScalar(loc, builder, result); if (result.isVariable()) - result = hlfir::Entity{builder.create(loc, result)}; + result = hlfir::Entity{hlfir::AsExprOp::create(builder, loc, result)}; for (auto associate : exprAssociations) - builder.create(loc, associate); + hlfir::EndAssociateOp::create(builder, loc, associate); return hlfir::EntityWithAttributes{result}; } @@ -952,9 +951,9 @@ extendedValueToHlfirEntity(mlir::Location loc, fir::FirOpBuilder &builder, // rid of the memory indirection in a = char(b), so there is // little incentive to increase the compiler complexity. hlfir::Entity storage{builder.createTemporary(loc, charTy)}; - builder.create(loc, firBase, storage); - auto asExpr = builder.create( - loc, storage, /*mustFree=*/builder.createBool(loc, false)); + fir::StoreOp::create(builder, loc, firBase, storage); + auto asExpr = hlfir::AsExprOp::create( + builder, loc, storage, /*mustFree=*/builder.createBool(loc, false)); return hlfir::EntityWithAttributes{asExpr.getResult()}; } return hlfir::genDeclare(loc, builder, exv, name, @@ -966,7 +965,7 @@ namespace { struct CallCleanUp { struct CopyIn { void genCleanUp(mlir::Location loc, fir::FirOpBuilder &builder) { - builder.create(loc, tempBox, wasCopied, copyBackVar); + hlfir::CopyOutOp::create(builder, loc, tempBox, wasCopied, copyBackVar); } // address of the descriptor holding the temp if a temp was created. mlir::Value tempBox; @@ -977,7 +976,7 @@ struct CallCleanUp { }; struct ExprAssociate { void genCleanUp(mlir::Location loc, fir::FirOpBuilder &builder) { - builder.create(loc, tempVar, mustFree); + hlfir::EndAssociateOp::create(builder, loc, tempVar, mustFree); } mlir::Value tempVar; mlir::Value mustFree; @@ -1075,7 +1074,7 @@ struct ConditionallyPreparedDummy { /// Generate the "fir.result %preparedDummy" in the then branch of the /// wrapping fir.if. void genThenResult(mlir::Location loc, fir::FirOpBuilder &builder) const { - builder.create(loc, thenResultValues); + fir::ResultOp::create(builder, loc, thenResultValues); } /// Generate the "fir.result %absent" in the else branch of the @@ -1090,7 +1089,7 @@ struct ConditionallyPreparedDummy { else elseResultValues.push_back(builder.genAbsentOp(loc, type)); } - builder.create(loc, elseResultValues); + fir::ResultOp::create(builder, loc, elseResultValues); } /// Once the fir.if has been created, get the resulting %conditionallyPrepared @@ -1135,7 +1134,7 @@ static hlfir::Entity fixProcedureDummyMismatch(mlir::Location loc, if (mlir::isa(actual.getType()) && fir::isCharacterProcedureTuple(dummyType)) { mlir::Value length = - builder.create(loc, builder.getCharacterLengthType()); + fir::UndefOp::create(builder, loc, builder.getCharacterLengthType()); mlir::Value tuple = fir::factory::createCharacterProcedureTuple( builder, loc, dummyType, actual, length); return hlfir::Entity{tuple}; @@ -1318,8 +1317,8 @@ static PreparedDummyArgument preparePresentUserCallActualArgument( mlir::Type tempBoxType = baseBoxTy.getBoxTypeWithNewAttr( fir::BaseBoxType::Attribute::Allocatable); mlir::Value tempBox = builder.createTemporary(loc, tempBoxType); - auto copyIn = builder.create( - loc, var, tempBox, /*var_is_present=*/mlir::Value{}); + auto copyIn = hlfir::CopyInOp::create(builder, loc, var, tempBox, + /*var_is_present=*/mlir::Value{}); // Register the copy-out after the call. preparedDummy.pushCopyInCleanUp(copyIn.getTempBox(), copyIn.getWasCopied(), doCopyOut ? copyIn.getVar() @@ -1331,16 +1330,17 @@ static PreparedDummyArgument preparePresentUserCallActualArgument( fir::BaseBoxType boxType = fir::BoxType::get( hlfir::getFortranElementOrSequenceType(dummyTypeWithActualRank)); if (actualIsAssumedRank) - return hlfir::Entity{builder.create( - loc, boxType, var, fir::LowerBoundModifierAttribute::SetToOnes)}; + return hlfir::Entity{fir::ReboxAssumedRankOp::create( + builder, loc, boxType, var, + fir::LowerBoundModifierAttribute::SetToOnes)}; // Use actual shape when creating descriptor with dummy type, the dummy // shape may be unknown in case of sequence association. mlir::Type actualTy = hlfir::getFortranElementOrSequenceType(actual.getType()); boxType = boxType.getBoxTypeWithNewShape(actualTy); - return hlfir::Entity{builder.create(loc, boxType, var, - /*shape=*/mlir::Value{}, - /*slice=*/mlir::Value{})}; + return hlfir::Entity{fir::ReboxOp::create(builder, loc, boxType, var, + /*shape=*/mlir::Value{}, + /*slice=*/mlir::Value{})}; }; // Step 2: prepare the storage for the dummy arguments, ensuring that it @@ -1362,7 +1362,7 @@ static PreparedDummyArgument preparePresentUserCallActualArgument( // generated writes in copy-out. isParameterObjectOrSubObject(entity)) { // Make a copy in a temporary. - auto copy = builder.create(loc, entity); + auto copy = hlfir::AsExprOp::create(builder, loc, entity); mlir::Type storageType = entity.getType(); mlir::NamedAttribute byRefAttr = fir::getAdaptToByRefAttr(builder); hlfir::AssociateOp associate = hlfir::genAssociateExpr( @@ -1442,14 +1442,14 @@ static PreparedDummyArgument preparePresentUserCallActualArgument( auto lbModifier = needsZeroLowerBounds ? fir::LowerBoundModifierAttribute::SetToZeroes : fir::LowerBoundModifierAttribute::SetToOnes; - entity = hlfir::Entity{builder.create( - loc, dummyTypeWithActualRank, entity, lbModifier)}; + entity = hlfir::Entity{fir::ReboxAssumedRankOp::create( + builder, loc, dummyTypeWithActualRank, entity, lbModifier)}; } else { mlir::Value shift{}; if (needsZeroLowerBounds) shift = getZeroLowerBounds(loc, builder, entity); - entity = hlfir::Entity{builder.create( - loc, dummyTypeWithActualRank, entity, /*shape=*/shift, + entity = hlfir::Entity{fir::ReboxOp::create( + builder, loc, dummyTypeWithActualRank, entity, /*shape=*/shift, /*slice=*/mlir::Value{})}; } } @@ -1502,8 +1502,8 @@ static PreparedDummyArgument prepareUserCallActualArgument( // for this unusual if/then/else generation is that the number // and types of the if results will depend on how the argument // is prepared, and forecasting that here would be brittle. - auto badIfOp = builder.create(loc, dummyType, isPresent, - /*withElseRegion=*/false); + auto badIfOp = fir::IfOp::create(builder, loc, dummyType, isPresent, + /*withElseRegion=*/false); mlir::Block *preparationBlock = &badIfOp.getThenRegion().front(); builder.setInsertionPointToStart(preparationBlock); PreparedDummyArgument unconditionalDummy = @@ -1521,9 +1521,9 @@ static PreparedDummyArgument prepareUserCallActualArgument( // badIfOp cannot be modified and used here). llvm::SmallVector ifOpResultTypes; ConditionallyPreparedDummy conditionalDummy(unconditionalDummy); - auto ifOp = builder.create(loc, conditionalDummy.getIfResulTypes(), - isPresent, - /*withElseRegion=*/true); + auto ifOp = fir::IfOp::create(builder, loc, + conditionalDummy.getIfResulTypes(), isPresent, + /*withElseRegion=*/true); // Move "preparationBlock" into the "then" of the new // fir.if operation and create fir.result propagating // unconditionalDummy. @@ -1560,7 +1560,7 @@ static PreparedDummyArgument prepareProcedurePointerActualArgument( auto tempBoxProc{builder.createTemporary(loc, boxTy)}; hlfir::Entity nullBoxProc( fir::factory::createNullBoxProc(builder, loc, boxTy)); - builder.create(loc, nullBoxProc, tempBoxProc); + fir::StoreOp::create(builder, loc, nullBoxProc, tempBoxProc); return PreparedDummyArgument{tempBoxProc, /*cleanups=*/{}}; } hlfir::Entity actual = preparedActual.getActual(loc, builder); @@ -1569,7 +1569,7 @@ static PreparedDummyArgument prepareProcedurePointerActualArgument( assert(actual.isProcedure()); // Procedure actual to procedure pointer dummy. auto tempBoxProc{builder.createTemporary(loc, actual.getType())}; - builder.create(loc, actual, tempBoxProc); + fir::StoreOp::create(builder, loc, actual, tempBoxProc); return PreparedDummyArgument{tempBoxProc, /*cleanups=*/{}}; } @@ -1608,7 +1608,7 @@ void prepareUserCallArguments( "adapt.cptrbyval"); value = hlfir::Entity{genRecordCPtrValueArg( builder, loc, associate.getFirBase(), eleTy)}; - builder.create(loc, associate); + hlfir::EndAssociateOp::create(builder, loc, associate); } else { value = hlfir::Entity{genRecordCPtrValueArg(builder, loc, value, eleTy)}; @@ -1627,7 +1627,7 @@ void prepareUserCallArguments( loadedValue = builder.createConvert( loc, fir::ReferenceType::get(argTy), loadedValue); if (fir::isa_ref_type(loadedValue.getType())) - loadedValue = builder.create(loc, loadedValue); + loadedValue = fir::LoadOp::create(builder, loc, loadedValue); caller.placeInput(arg, loadedValue); if (cleanup) (*cleanup)(); @@ -1714,7 +1714,7 @@ void prepareUserCallArguments( /*nonDeferredParams=*/mlir::ValueRange{}, /*mutableProperties=*/{}); fir::factory::associateMutableBox(builder, loc, ptrBox, actualExv, - /*lbounds=*/std::nullopt); + /*lbounds=*/{}); caller.placeInput(arg, irBox); continue; } @@ -1812,8 +1812,9 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals, // In such case, the expression should not be freed after its use since // the result is stack allocated or deallocation (for allocatable results) // was already inserted in genCallOpAndResult. - auto asExpr = builder.create( - loc, resultEntity, /*mustFree=*/builder.createBool(loc, false)); + auto asExpr = + hlfir::AsExprOp::create(builder, loc, resultEntity, + /*mustFree=*/builder.createBool(loc, false)); return hlfir::EntityWithAttributes{asExpr.getResult()}; } return hlfir::EntityWithAttributes{resultEntity}; @@ -1861,12 +1862,12 @@ static ExvAndCleanup genOptionalValue(fir::FirOpBuilder &builder, "must be a numerical or logical scalar"); mlir::Value val = hlfir::loadTrivialScalar(loc, builder, entity); - builder.create(loc, val); + fir::ResultOp::create(builder, loc, val); }) .genElse([&]() { mlir::Value zero = fir::factory::createZeroValue(builder, loc, eleType); - builder.create(loc, zero); + fir::ResultOp::create(builder, loc, zero); }) .getResults()[0], std::nullopt}; @@ -1913,9 +1914,9 @@ static ExvAndCleanup genOptionalBox(fir::FirOpBuilder &builder, // ensures it won't be. mlir::Value box = builder.createBox(loc, newExv); mlir::Type boxType = box.getType(); - auto absent = builder.create(loc, boxType); - auto boxOrAbsent = builder.create( - loc, boxType, isPresent, box, absent); + auto absent = fir::AbsentOp::create(builder, loc, boxType); + auto boxOrAbsent = mlir::arith::SelectOp::create(builder, loc, boxType, + isPresent, box, absent); return {fir::BoxValue(boxOrAbsent), cleanup}; } @@ -2143,10 +2144,10 @@ genIntrinsicRefCore(Fortran::lower::PreparedActualArguments &loweredActuals, // ownership of this address cannot be taken here since it may not be a // temp. if (intrinsicName == "merge") - asExpr = builder.create(loc, resultEntity); + asExpr = hlfir::AsExprOp::create(builder, loc, resultEntity); else - asExpr = builder.create( - loc, resultEntity, builder.createBool(loc, mustBeFreed)); + asExpr = hlfir::AsExprOp::create(builder, loc, resultEntity, + builder.createBool(loc, mustBeFreed)); resultEntity = hlfir::EntityWithAttributes{asExpr.getResult()}; } return resultEntity; @@ -2526,7 +2527,7 @@ genIsPresentIfArgMaybeAbsent(mlir::Location loc, hlfir::Entity actual, // May fall into the category above if the allocatable is not optional. // Passing an optional to an optional. - return builder.create(loc, builder.getI1Type(), actual) + return fir::IsPresentOp::create(builder, loc, builder.getI1Type(), actual) .getResult(); } @@ -2814,9 +2815,9 @@ genProcedureRef(CallContext &callContext) { // TYPE(*) cannot be ALLOCATABLE/POINTER (C709) so there is no // need to cover the case of passing an ALLOCATABLE/POINTER to an // OPTIONAL. - isPresent = - builder.create(loc, builder.getI1Type(), actual) - .getResult(); + isPresent = fir::IsPresentOp::create(builder, loc, + builder.getI1Type(), actual) + .getResult(); } loweredActuals.push_back(Fortran::lower::PreparedActualArgument{ hlfir::Entity{*var}, isPresent}); @@ -2932,7 +2933,7 @@ std::optional Fortran::lower::convertCallToHLFIR( // this can be enforced whenscheduling forall/where expression evaluations. Fortran::lower::StatementContext localStmtCtx; mlir::Type bogusType = builder.getIndexType(); - auto exactlyOnce = builder.create(loc, bogusType); + auto exactlyOnce = hlfir::ExactlyOnceOp::create(builder, loc, bogusType); mlir::Block *block = builder.createBlock(&exactlyOnce.getBody()); builder.setInsertionPointToStart(block); CallContext callContext(procRef, resultType, loc, converter, symMap, @@ -2940,7 +2941,7 @@ std::optional Fortran::lower::convertCallToHLFIR( std::optional res = genProcedureRef(callContext); assert(res.has_value() && "must be a function"); - auto yield = builder.create(loc, *res); + auto yield = hlfir::YieldOp::create(builder, loc, *res); Fortran::lower::genCleanUpInRegionIfAny(loc, builder, yield.getCleanup(), localStmtCtx); builder.setInsertionPointAfter(exactlyOnce); diff --git a/flang/lib/Lower/ConvertConstant.cpp b/flang/lib/Lower/ConvertConstant.cpp index 1051d50ce8a9a..768a237c92396 100644 --- a/flang/lib/Lower/ConvertConstant.cpp +++ b/flang/lib/Lower/ConvertConstant.cpp @@ -237,8 +237,8 @@ static mlir::Value genScalarLit( ? value.UnsignedDecimal() : value.SignedDecimal(), 10); - return builder.create( - loc, ty, mlir::IntegerAttr::get(ty, bigInt)); + return mlir::arith::ConstantOp::create( + builder, loc, ty, mlir::IntegerAttr::get(ty, bigInt)); } return builder.createIntegerConstant(loc, ty, value.ToInt64()); } else if constexpr (TC == Fortran::common::TypeCategory::Logical) { @@ -302,8 +302,9 @@ createStringLitOp(fir::FirOpBuilder &builder, mlir::Location loc, auto sizeTag = mlir::StringAttr::get(context, fir::StringLitOp::size()); mlir::NamedAttribute sizeAttr(sizeTag, builder.getI64IntegerAttr(len)); llvm::SmallVector attrs = {dataAttr, sizeAttr}; - return builder.create( - loc, llvm::ArrayRef{type}, std::nullopt, attrs); + return fir::StringLitOp::create(builder, loc, + llvm::ArrayRef{type}, + mlir::ValueRange{}, attrs); } } @@ -340,11 +341,11 @@ genScalarLit(fir::FirOpBuilder &builder, mlir::Location loc, [&](fir::FirOpBuilder &builder) { fir::StringLitOp str = createStringLitOp(builder, loc, value, len); - builder.create(loc, str); + fir::HasValueOp::create(builder, loc, str); }, builder.createLinkOnceLinkage()); - return builder.create(loc, global.resultType(), - global.getSymbol()); + return fir::AddrOfOp::create(builder, loc, global.resultType(), + global.getSymbol()); } // Helper to generate StructureConstructor component values. @@ -364,9 +365,9 @@ static mlir::Value genStructureComponentInit( auto fieldTy = fir::FieldType::get(recTy.getContext()); assert(componentTy && "failed to retrieve component"); // FIXME: type parameters must come from the derived-type-spec - auto field = builder.create( - loc, fieldTy, name, recTy, - /*typeParams=*/mlir::ValueRange{} /*TODO*/); + auto field = + fir::FieldIndexOp::create(builder, loc, fieldTy, name, recTy, + /*typeParams=*/mlir::ValueRange{} /*TODO*/); if (Fortran::semantics::IsAllocatable(sym)) { if (!Fortran::evaluate::IsNullPointerOrAllocatable(&expr)) { @@ -374,12 +375,12 @@ static mlir::Value genStructureComponentInit( "allocatable component value that is not NULL"); } else { // Handle NULL() initialization - mlir::Value componentValue{fir::factory::createUnallocatedBox( - builder, loc, componentTy, std::nullopt)}; + mlir::Value componentValue{ + fir::factory::createUnallocatedBox(builder, loc, componentTy, {})}; componentValue = builder.createConvert(loc, componentTy, componentValue); - return builder.create( - loc, recTy, res, componentValue, + return fir::InsertValueOp::create( + builder, loc, recTy, res, componentValue, builder.getArrayAttr(field.getAttributes())); } } @@ -400,9 +401,9 @@ static mlir::Value genStructureComponentInit( } else initialTarget = Fortran::lower::genInitialDataTarget(converter, loc, componentTy, expr); - res = builder.create( - loc, recTy, res, initialTarget, - builder.getArrayAttr(field.getAttributes())); + res = + fir::InsertValueOp::create(builder, loc, recTy, res, initialTarget, + builder.getArrayAttr(field.getAttributes())); return res; } @@ -426,7 +427,7 @@ static mlir::Value genStructureComponentInit( mlir::Value addr = fir::getBase( Fortran::lower::genExtAddrInInitializer(converter, loc, expr)); if (mlir::isa(addr.getType())) - addr = builder.create(loc, addr); + addr = fir::BoxAddrOp::create(builder, loc, addr); assert((fir::isa_ref_type(addr.getType()) || mlir::isa(addr.getType())) && "expect reference type for address field"); @@ -435,24 +436,25 @@ static mlir::Value genStructureComponentInit( auto cPtrRecTy = mlir::cast(componentTy); llvm::StringRef addrFieldName = Fortran::lower::builtin::cptrFieldName; mlir::Type addrFieldTy = cPtrRecTy.getType(addrFieldName); - auto addrField = builder.create( - loc, fieldTy, addrFieldName, componentTy, + auto addrField = fir::FieldIndexOp::create( + builder, loc, fieldTy, addrFieldName, componentTy, /*typeParams=*/mlir::ValueRange{}); mlir::Value castAddr = builder.createConvert(loc, addrFieldTy, addr); - auto undef = builder.create(loc, componentTy); - addr = builder.create( - loc, componentTy, undef, castAddr, + auto undef = fir::UndefOp::create(builder, loc, componentTy); + addr = fir::InsertValueOp::create( + builder, loc, componentTy, undef, castAddr, builder.getArrayAttr(addrField.getAttributes())); - res = builder.create( - loc, recTy, res, addr, builder.getArrayAttr(field.getAttributes())); + res = + fir::InsertValueOp::create(builder, loc, recTy, res, addr, + builder.getArrayAttr(field.getAttributes())); return res; } mlir::Value val = fir::getBase(genConstantValue(converter, loc, expr)); assert(!fir::isa_ref_type(val.getType()) && "expecting a constant value"); mlir::Value castVal = builder.createConvert(loc, componentTy, val); - res = builder.create( - loc, recTy, res, castVal, builder.getArrayAttr(field.getAttributes())); + res = fir::InsertValueOp::create(builder, loc, recTy, res, castVal, + builder.getArrayAttr(field.getAttributes())); return res; } @@ -465,7 +467,7 @@ static mlir::Value genInlinedStructureCtorLitImpl( auto recTy = mlir::cast(type); if (!converter.getLoweringOptions().getLowerToHighLevelFIR()) { - mlir::Value res = builder.create(loc, recTy); + mlir::Value res = fir::UndefOp::create(builder, loc, recTy); for (const auto &[sym, expr] : ctor.values()) { // Parent components need more work because they do not appear in the // fir.rec type. @@ -495,13 +497,13 @@ static mlir::Value genInlinedStructureCtorLitImpl( break; } for (mlir::Type parentType : llvm::reverse(parentTypes)) { - auto undef = builder.create(loc, parentType); + auto undef = fir::UndefOp::create(builder, loc, parentType); fir::RecordType parentRecTy = mlir::cast(parentType); - auto field = builder.create( - loc, fieldTy, parentRecTy.getTypeList()[0].first, parentType, + auto field = fir::FieldIndexOp::create( + builder, loc, fieldTy, parentRecTy.getTypeList()[0].first, parentType, /*typeParams=*/mlir::ValueRange{} /*TODO*/); - res = builder.create( - loc, parentRecTy, undef, res, + res = fir::InsertValueOp::create( + builder, loc, parentRecTy, undef, res, builder.getArrayAttr(field.getAttributes())); } }; @@ -514,7 +516,7 @@ static mlir::Value genInlinedStructureCtorLitImpl( if (!res) { mlir::Type parentType = converter.genType(*componentParentType); curentType = componentParentType; - res = builder.create(loc, parentType); + res = fir::UndefOp::create(builder, loc, parentType); } else if (*componentParentType != *curentType) { mlir::Type parentType = converter.genType(*componentParentType); insertParentValueIntoExtension(parentType); @@ -524,7 +526,7 @@ static mlir::Value genInlinedStructureCtorLitImpl( } if (!res) // structure constructor for empty type. - return builder.create(loc, recTy); + return fir::UndefOp::create(builder, loc, recTy); // The last component may belong to a parent type. if (res.getType() != recTy) @@ -550,12 +552,12 @@ static mlir::Value genScalarLit( [&](fir::FirOpBuilder &builder) { mlir::Value result = genInlinedStructureCtorLitImpl(converter, loc, value, eleTy); - builder.create(loc, result); + fir::HasValueOp::create(builder, loc, result); }, builder.createInternalLinkage()); } - return builder.create(loc, global.resultType(), - global.getSymbol()); + return fir::AddrOfOp::create(builder, loc, global.resultType(), + global.getSymbol()); } /// Create an evaluate::Constant array to a fir.array<> value @@ -576,7 +578,7 @@ genInlinedArrayLit(Fortran::lower::AbstractConverter &converter, builder.getIntegerAttr(idxTy, subscripts[i] - con.lbounds()[i])); return idx; }; - mlir::Value array = builder.create(loc, arrayTy); + mlir::Value array = fir::UndefOp::create(builder, loc, arrayTy); if (Fortran::evaluate::GetSize(con.shape()) == 0) return array; if constexpr (T::category == Fortran::common::TypeCategory::Character) { @@ -584,8 +586,9 @@ genInlinedArrayLit(Fortran::lower::AbstractConverter &converter, mlir::Value elementVal = genScalarLit(builder, loc, con.At(subscripts), con.LEN(), /*outlineInReadOnlyMemory=*/false); - array = builder.create( - loc, arrayTy, array, elementVal, builder.getArrayAttr(createIdx())); + array = + fir::InsertValueOp::create(builder, loc, arrayTy, array, elementVal, + builder.getArrayAttr(createIdx())); } while (con.IncrementSubscripts(subscripts)); } else if constexpr (T::category == Fortran::common::TypeCategory::Derived) { do { @@ -594,8 +597,9 @@ genInlinedArrayLit(Fortran::lower::AbstractConverter &converter, mlir::Value elementVal = genScalarLit(converter, loc, con.At(subscripts), eleTy, /*outlineInReadOnlyMemory=*/false); - array = builder.create( - loc, arrayTy, array, elementVal, builder.getArrayAttr(createIdx())); + array = + fir::InsertValueOp::create(builder, loc, arrayTy, array, elementVal, + builder.getArrayAttr(createIdx())); } while (con.IncrementSubscripts(subscripts)); } else { llvm::SmallVector rangeStartIdx; @@ -611,9 +615,9 @@ genInlinedArrayLit(Fortran::lower::AbstractConverter &converter, bool nextIsSame = con.IncrementSubscripts(nextSubscripts) && con.At(subscripts) == con.At(nextSubscripts); if (!rangeSize && !nextIsSame) { // single (non-range) value - array = builder.create( - loc, arrayTy, array, getElementVal(), - builder.getArrayAttr(createIdx())); + array = fir::InsertValueOp::create(builder, loc, arrayTy, array, + getElementVal(), + builder.getArrayAttr(createIdx())); } else if (!rangeSize) { // start a range rangeStartIdx = createIdx(); rangeSize = 1; @@ -629,8 +633,8 @@ genInlinedArrayLit(Fortran::lower::AbstractConverter &converter, rangeBounds.push_back( mlir::cast(idx[i]).getValue().getSExtValue()); } - array = builder.create( - loc, arrayTy, array, getElementVal(), + array = fir::InsertOnRangeOp::create( + builder, loc, arrayTy, array, getElementVal(), builder.getIndexVectorAttr(rangeBounds)); rangeSize = 0; } @@ -679,12 +683,12 @@ genOutlineArrayLit(Fortran::lower::AbstractConverter &converter, [&](fir::FirOpBuilder &builder) { mlir::Value result = genInlinedArrayLit(converter, loc, arrayTy, constant); - builder.create(loc, result); + fir::HasValueOp::create(builder, loc, result); }, builder.createInternalLinkage()); } - return builder.create(loc, global.resultType(), - global.getSymbol()); + return fir::AddrOfOp::create(builder, loc, global.resultType(), + global.getSymbol()); } /// Convert an evaluate::Constant array into an fir::ExtendedValue. diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp index f3430bfa3021e..3578f941ec1b4 100644 --- a/flang/lib/Lower/ConvertExpr.cpp +++ b/flang/lib/Lower/ConvertExpr.cpp @@ -267,8 +267,8 @@ static mlir::Value genActualIsPresentTest(fir::FirOpBuilder &builder, // Optional case (not that optional allocatable/pointer cannot be absent // when passed to CMPLX as per 15.5.2.12 point 3 (7) and (8)). It is // therefore possible to catch them in the `then` case above. - return builder.create(loc, builder.getI1Type(), - fir::getBase(actual)); + return fir::IsPresentOp::create(builder, loc, builder.getI1Type(), + fir::getBase(actual)); } /// Convert the array_load, `load`, to an extended value. If `path` is not @@ -345,8 +345,8 @@ arrayLoadExtValue(fir::FirOpBuilder &builder, mlir::Location loc, auto origins = fir::factory::getNonDefaultLowerBounds(builder, loc, exv); if (shapeVal) { // shapeVal is a ShiftOp and load.memref() is a boxed value. - newBase = builder.create(loc, oldBox.getType(), oldBox, - shapeVal, /*slice=*/mlir::Value{}); + newBase = fir::ReboxOp::create(builder, loc, oldBox.getType(), oldBox, + shapeVal, /*slice=*/mlir::Value{}); origins = fir::factory::getOrigins(shapeVal); } return fir::substBase(arrayToExtendedValue(extents, origins), newBase); @@ -378,7 +378,7 @@ placeScalarValueInMemory(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value temp = builder.createTemporary( loc, storageType, llvm::ArrayRef{fir::getAdaptToByRefAttr(builder)}); - builder.create(loc, val, temp); + fir::StoreOp::create(builder, loc, val, temp); return fir::substBase(exv, temp); } @@ -434,14 +434,14 @@ static fir::ExtendedValue genLoad(fir::FirOpBuilder &builder, if (mlir::isa( fir::unwrapRefType(fir::getBase(p).getType()))) return p; - mlir::Value load = builder.create(loc, fir::getBase(p)); + mlir::Value load = fir::LoadOp::create(builder, loc, fir::getBase(p)); return fir::PolymorphicValue(load, p.getSourceBox()); }, [&](const fir::UnboxedValue &v) -> fir::ExtendedValue { if (mlir::isa( fir::unwrapRefType(fir::getBase(v).getType()))) return v; - return builder.create(loc, fir::getBase(v)); + return fir::LoadOp::create(builder, loc, fir::getBase(v)); }, [&](const fir::MutableBoxValue &box) -> fir::ExtendedValue { return genLoad(builder, loc, @@ -473,11 +473,11 @@ static fir::ExtendedValue genOptionalValue(fir::FirOpBuilder &builder, /*withElseRegion=*/true) .genThen([&]() { mlir::Value val = fir::getBase(genLoad(builder, loc, exv)); - builder.create(loc, val); + fir::ResultOp::create(builder, loc, val); }) .genElse([&]() { mlir::Value zero = fir::factory::createZeroValue(builder, loc, eleType); - builder.create(loc, zero); + fir::ResultOp::create(builder, loc, zero); }) .getResults()[0]; } @@ -521,9 +521,9 @@ static fir::ExtendedValue genOptionalBox(fir::FirOpBuilder &builder, // ensures it won't be. mlir::Value box = builder.createBox(loc, newExv); mlir::Type boxType = box.getType(); - auto absent = builder.create(loc, boxType); - auto boxOrAbsent = builder.create( - loc, boxType, isPresent, box, absent); + auto absent = fir::AbsentOp::create(builder, loc, boxType); + auto boxOrAbsent = mlir::arith::SelectOp::create(builder, loc, boxType, + isPresent, box, absent); return fir::BoxValue(boxOrAbsent); } @@ -569,13 +569,13 @@ createBoxProcCharTuple(Fortran::lower::AbstractConverter &converter, if (fir::isa_ref_type(fromTy)) funcAddr = builder.createConvert(loc, toTy, funcAddr); else if (mlir::isa(fromTy)) - funcAddr = builder.create(loc, toTy, funcAddr); + funcAddr = fir::BoxAddrOp::create(builder, loc, toTy, funcAddr); auto boxProc = [&]() -> mlir::Value { if (auto host = Fortran::lower::argumentHostAssocs(converter, funcAddr)) - return builder.create( - loc, boxTy, llvm::ArrayRef{funcAddr, host}); - return builder.create(loc, boxTy, funcAddr); + return fir::EmboxProcOp::create( + builder, loc, boxTy, llvm::ArrayRef{funcAddr, host}); + return fir::EmboxProcOp::create(builder, loc, boxTy, funcAddr); }(); return fir::factory::createCharacterProcedureTuple(builder, loc, argTy, boxProc, charLen); @@ -596,9 +596,9 @@ absentBoxToUnallocatedBox(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type boxType = box.getType(); assert(mlir::isa(boxType) && "argument must be a fir.box"); mlir::Value emptyBox = - fir::factory::createUnallocatedBox(builder, loc, boxType, std::nullopt); + fir::factory::createUnallocatedBox(builder, loc, boxType, {}); auto safeToReadBox = - builder.create(loc, isPresent, box, emptyBox); + mlir::arith::SelectOp::create(builder, loc, isPresent, box, emptyBox); return fir::substBase(exv, safeToReadBox); } @@ -822,9 +822,9 @@ class ScalarExprLowering { Fortran::common::TypeCategory::Integer, *unsignedKind); mlir::Value lhsSL = builder.createConvert(loc, signlessType, *lhs); mlir::Value rhsSL = builder.createConvert(loc, signlessType, *rhs); - return builder.create(loc, pred, lhsSL, rhsSL); + return OpTy::create(builder, loc, pred, lhsSL, rhsSL); } - return builder.create(loc, pred, *lhs, *rhs); + return OpTy::create(builder, loc, pred, *lhs, *rhs); } } fir::emitFatalError(getLoc(), "array compare should be handled in genarr"); @@ -841,7 +841,7 @@ class ScalarExprLowering { const ExtValue &left, const ExtValue &right) { if (const fir::UnboxedValue *lhs = left.getUnboxed()) if (const fir::UnboxedValue *rhs = right.getUnboxed()) - return builder.create(getLoc(), pred, *lhs, *rhs); + return OpTy::create(builder, getLoc(), pred, *lhs, *rhs); fir::emitFatalError(getLoc(), "array compare should be handled in genarr"); } template @@ -904,7 +904,7 @@ class ScalarExprLowering { mlir::Value cnvrt = Fortran::lower::addCrayPointerInst( loc, builder, ptrVal, ptrTy, pteVal.getType()); - addr = builder.create(loc, cnvrt); + addr = fir::LoadOp::create(builder, loc, cnvrt); } return genLoad(addr); } @@ -970,12 +970,12 @@ class ScalarExprLowering { std::string name = converter.getRecordTypeFieldName(sym); // FIXME: type parameters must come from the derived-type-spec - mlir::Value field = builder.create( - loc, fieldTy, name, ty, - /*typeParams=*/mlir::ValueRange{} /*TODO*/); + mlir::Value field = + fir::FieldIndexOp::create(builder, loc, fieldTy, name, ty, + /*typeParams=*/mlir::ValueRange{} /*TODO*/); mlir::Type coorTy = builder.getRefType(recTy.getType(name)); - auto coor = builder.create(loc, coorTy, - fir::getBase(res), field); + auto coor = fir::CoordinateOp::create(builder, loc, coorTy, + fir::getBase(res), field); ExtValue to = fir::factory::componentToExtendedValue(builder, loc, coor); to.match( [&](const fir::UnboxedValue &toPtr) { @@ -1003,9 +1003,9 @@ class ScalarExprLowering { }, [&](const fir::MutableBoxValue &toBox) { if (toBox.isPointer()) { - Fortran::lower::associateMutableBox(converter, loc, toBox, expr, - /*lbounds=*/std::nullopt, - stmtCtx); + Fortran::lower::associateMutableBox( + converter, loc, toBox, expr, + /*lbounds=*/mlir::ValueRange{}, stmtCtx); return; } // For allocatable components, a deep copy is needed. @@ -1077,7 +1077,7 @@ class ScalarExprLowering { mlir::Value input = genunbox(op.left()); // Like LLVM, integer negation is the binary op "0 - value" mlir::Value zero = genIntegerConstant(builder.getContext(), 0); - return builder.create(getLoc(), zero, input); + return mlir::arith::SubIOp::create(builder, getLoc(), zero, input); } template ExtValue genval(const Fortran::evaluate::Negate(builder.getContext(), 0); - mlir::Value neg = builder.create(loc, zero, signless); + mlir::Value neg = mlir::arith::SubIOp::create(builder, loc, zero, signless); return builder.createConvert(loc, input.getType(), neg); } template ExtValue genval(const Fortran::evaluate::Negate> &op) { - return builder.create(getLoc(), genunbox(op.left())); + return mlir::arith::NegFOp::create(builder, getLoc(), genunbox(op.left())); } template ExtValue genval(const Fortran::evaluate::Negate> &op) { - return builder.create(getLoc(), genunbox(op.left())); + return fir::NegcOp::create(builder, getLoc(), genunbox(op.left())); } template @@ -1312,7 +1312,7 @@ class ScalarExprLowering { ExtValue input = genval(op.left()); mlir::Value base = fir::getBase(input); mlir::Value newBase = - builder.create(getLoc(), base.getType(), base); + fir::NoReassocOp::create(builder, getLoc(), base.getType(), base); return fir::substBase(input, newBase); } @@ -1322,7 +1322,7 @@ class ScalarExprLowering { mlir::Value one = genBoolConstant(true); mlir::Value val = builder.createConvert(getLoc(), builder.getI1Type(), logical); - return builder.create(getLoc(), val, one); + return mlir::arith::XOrIOp::create(builder, getLoc(), val, one); } template @@ -1384,8 +1384,9 @@ class ScalarExprLowering { mlir::Value offset = builder.createIntegerConstant( loc, idxTy, x.part() == Fortran::evaluate::ComplexPart::Part::RE ? 0 : 1); - mlir::Value result = builder.create( - loc, builder.getRefType(eleTy), base, mlir::ValueRange{offset}); + mlir::Value result = + fir::CoordinateOp::create(builder, loc, builder.getRefType(eleTy), base, + mlir::ValueRange{offset}); return {result}; } ExtValue genval(const Fortran::evaluate::ComplexPart &x) { @@ -1500,8 +1501,8 @@ class ScalarExprLowering { auto recTy = mlir::cast(ty); const Fortran::semantics::Symbol &sym = getLastSym(*field); std::string name = converter.getRecordTypeFieldName(sym); - coorArgs.push_back(builder.create( - loc, fldTy, name, recTy, fir::getTypeParams(obj))); + coorArgs.push_back(fir::FieldIndexOp::create( + builder, loc, fldTy, name, recTy, fir::getTypeParams(obj))); ty = recTy.getType(name); } // If parent component is referred then it has no coordinate argument. @@ -1510,8 +1511,8 @@ class ScalarExprLowering { ty = builder.getRefType(ty); return fir::factory::componentToExtendedValue( builder, loc, - builder.create(loc, ty, fir::getBase(obj), - coorArgs)); + fir::CoordinateOp::create(builder, loc, ty, fir::getBase(obj), + coorArgs)); } ExtValue gen(const Fortran::evaluate::Component &cmpt) { @@ -1587,7 +1588,7 @@ class ScalarExprLowering { mlir::Value val = fir::getBase(subVal); mlir::Type ty = val.getType(); mlir::Value lb = getLBound(array, subsc.index(), ty); - args.push_back(builder.create(loc, ty, val, lb)); + args.push_back(mlir::arith::SubIOp::create(builder, loc, ty, val, lb)); } mlir::Value base = fir::getBase(array); @@ -1602,7 +1603,7 @@ class ScalarExprLowering { mlir::Value cnvrt = Fortran::lower::addCrayPointerInst( loc, builder, ptrVal, ptrTy, base.getType()); - base = builder.create(loc, cnvrt); + base = fir::LoadOp::create(builder, loc, cnvrt); } mlir::Type eleTy = fir::dyn_cast_ptrOrBoxEleTy(base.getType()); @@ -1611,7 +1612,7 @@ class ScalarExprLowering { auto seqTy = mlir::cast(eleTy); assert(args.size() == seqTy.getDimension()); mlir::Type ty = builder.getRefType(seqTy.getEleTy()); - auto addr = builder.create(loc, ty, base, args); + auto addr = fir::CoordinateOp::create(builder, loc, ty, base, args); return fir::factory::arrayElementToExtendedValue(builder, loc, array, addr); } @@ -1648,12 +1649,12 @@ class ScalarExprLowering { mlir::Value val = builder.createConvert(loc, idxTy, fir::getBase(subVal)); mlir::Value lb = builder.createConvert(loc, idxTy, getLB(arr, dim)); - mlir::Value diff = builder.create(loc, val, lb); + mlir::Value diff = mlir::arith::SubIOp::create(builder, loc, val, lb); mlir::Value prod = - builder.create(loc, delta, diff); - total = builder.create(loc, prod, total); + mlir::arith::MulIOp::create(builder, loc, delta, diff); + total = mlir::arith::AddIOp::create(builder, loc, prod, total); if (ext) - delta = builder.create(loc, delta, ext); + delta = mlir::arith::MulIOp::create(builder, loc, delta, ext); ++dim; } mlir::Type origRefTy = refTy; @@ -1672,8 +1673,8 @@ class ScalarExprLowering { base = builder.createConvert(loc, seqRefTy, base); } } - auto coor = builder.create( - loc, refTy, base, llvm::ArrayRef{total}); + auto coor = fir::CoordinateOp::create(builder, loc, refTy, base, + llvm::ArrayRef{total}); // Convert to expected, original type after address arithmetic. return builder.createConvert(loc, origRefTy, coor); }; @@ -1725,9 +1726,9 @@ class ScalarExprLowering { builder.createConvert(loc, idxTy, fir::getBase(subVal))); } mlir::Value shape = builder.createShape(loc, exv); - mlir::Value elementAddr = builder.create( - loc, refTy, addr, shape, /*slice=*/mlir::Value{}, arrayCoorArgs, - fir::getTypeParams(exv)); + mlir::Value elementAddr = fir::ArrayCoorOp::create( + builder, loc, refTy, addr, shape, /*slice=*/mlir::Value{}, + arrayCoorArgs, fir::getTypeParams(exv)); return fir::factory::arrayElementToExtendedValue(builder, loc, exv, elementAddr); } @@ -1826,8 +1827,8 @@ class ScalarExprLowering { if (mlir::isa(exvTy)) { auto boxProcTy = builder.getBoxProcType(mlir::cast(exvTy)); - return builder.create(loc, boxProcTy, - fir::getBase(exv)); + return fir::EmboxProcOp::create(builder, loc, boxProcTy, + fir::getBase(exv)); } mlir::Value box = builder.createBox(loc, exv, exv.isPolymorphic()); if (Fortran::lower::isParentComponent(expr)) { @@ -2073,8 +2074,8 @@ class ScalarExprLowering { TODO(loc, "creating temporary for derived type with length parameters"); } - mlir::Value temp = builder.create( - loc, type, tempName, allocMemTypeParams, extents); + mlir::Value temp = fir::AllocMemOp::create(builder, loc, type, tempName, + allocMemTypeParams, extents); if (mlir::isa(fir::unwrapSequenceType(type))) return fir::CharArrayBoxValue{temp, charLen, extents}; return fir::ArrayBoxValue{temp, extents}; @@ -2124,9 +2125,9 @@ class ScalarExprLowering { mlir::Type type = v.getType(); mlir::Value value = v; if (fir::isa_ref_type(type)) - value = builder.create(loc, value); + value = fir::LoadOp::create(builder, loc, value); mlir::Value temp = builder.createTemporary(loc, value.getType()); - builder.create(loc, value, temp); + fir::StoreOp::create(builder, loc, value, temp); return temp; }, [&](const fir::BoxValue &x) -> ExtValue { @@ -2141,9 +2142,9 @@ class ScalarExprLowering { // created always has the declared type. mlir::Value var = fir::getBase(fir::factory::readBoxValue(builder, loc, x)); - auto value = builder.create(loc, var); + auto value = fir::LoadOp::create(builder, loc, var); mlir::Value temp = builder.createTemporary(loc, value.getType()); - builder.create(loc, value, temp); + fir::StoreOp::create(builder, loc, value, temp); return temp; }, [&](const fir::PolymorphicValue &p) -> ExtValue { @@ -2242,7 +2243,7 @@ class ScalarExprLowering { // at this point. mlir::Value destBox = fir::getBase(builder.createBox(loc, temp)); mlir::Value boxRef = builder.createTemporary(loc, destBox.getType()); - builder.create(loc, destBox, boxRef); + fir::StoreOp::create(builder, loc, destBox, boxRef); fir::runtime::genAssignTemporary(builder, loc, boxRef, fir::getBase(actualArg)); return temp; @@ -2250,21 +2251,22 @@ class ScalarExprLowering { auto noCopy = [&]() { mlir::Value box = fir::getBase(actualArg); - mlir::Value boxAddr = builder.create(loc, addrType, box); - builder.create(loc, boxAddr); + mlir::Value boxAddr = fir::BoxAddrOp::create(builder, loc, addrType, box); + fir::ResultOp::create(builder, loc, boxAddr); }; auto combinedCondition = [&]() { if (isActualArgBox) { mlir::Value zero = builder.createIntegerConstant(loc, builder.getI1Type(), 0); - mlir::Value notContiguous = builder.create( - loc, mlir::arith::CmpIPredicate::eq, isContiguousResult, zero); + mlir::Value notContiguous = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, isContiguousResult, + zero); if (!restrictCopyAtRuntime) { restrictCopyAtRuntime = notContiguous; } else { - mlir::Value cond = builder.create( - loc, *restrictCopyAtRuntime, notContiguous); + mlir::Value cond = mlir::arith::AndIOp::create( + builder, loc, *restrictCopyAtRuntime, notContiguous); restrictCopyAtRuntime = cond; } } @@ -2280,7 +2282,7 @@ class ScalarExprLowering { .genThen([&]() { noCopy(); }) .genElse([&] { ExtValue temp = doCopyIn(); - builder.create(loc, fir::getBase(temp)); + fir::ResultOp::create(builder, loc, fir::getBase(temp)); }) .getResults()[0]; fir::ExtendedValue temp = @@ -2312,19 +2314,19 @@ class ScalarExprLowering { .genThen([&]() { noCopy(); }) .genElse([&]() { ExtValue temp = doCopyIn(); - builder.create(loc, - fir::getBase(temp)); + fir::ResultOp::create(builder, loc, + fir::getBase(temp)); }) .getResults()[0]; - builder.create(loc, addr1); + fir::ResultOp::create(builder, loc, addr1); } else { ExtValue temp = doCopyIn(); - builder.create(loc, fir::getBase(temp)); + fir::ResultOp::create(builder, loc, fir::getBase(temp)); } }) .genElse([&]() { mlir::Value nullPtr = builder.createNullConstant(loc, addrType); - builder.create(loc, nullPtr); + fir::ResultOp::create(builder, loc, nullPtr); }) .getResults()[0]; // Associate the temp address with actualArg lengths and extents if a @@ -2357,7 +2359,7 @@ class ScalarExprLowering { tempBox); } // Deallocate the top-level entity of the temporary. - builder.create(loc, fir::getBase(copyOutPair.temp)); + fir::FreeMemOp::create(builder, loc, fir::getBase(copyOutPair.temp)); return; } // Generate CopyOutAssign() call to copy data from the temporary @@ -2376,11 +2378,11 @@ class ScalarExprLowering { mlir::Type allocBoxTy = mlir::cast(srcBox.getType()) .getBoxTypeWithNewAttr(fir::BaseBoxType::Attribute::Allocatable); - srcBox = builder.create(loc, allocBoxTy, srcBox, - /*shift=*/mlir::Value{}, - /*slice=*/mlir::Value{}); + srcBox = fir::ReboxOp::create(builder, loc, allocBoxTy, srcBox, + /*shift=*/mlir::Value{}, + /*slice=*/mlir::Value{}); mlir::Value srcBoxRef = builder.createTemporary(loc, srcBox.getType()); - builder.create(loc, srcBox, srcBoxRef); + fir::StoreOp::create(builder, loc, srcBox, srcBoxRef); // Create descriptor pointer to variable descriptor if copy out is needed, // and nullptr otherwise. mlir::Value destBoxRef; @@ -2388,9 +2390,9 @@ class ScalarExprLowering { mlir::Value destBox = fir::getBase(builder.createBox(loc, copyOutPair.var)); destBoxRef = builder.createTemporary(loc, destBox.getType()); - builder.create(loc, destBox, destBoxRef); + fir::StoreOp::create(builder, loc, destBox, destBoxRef); } else { - destBoxRef = builder.create(loc, srcBoxRef.getType()); + destBoxRef = fir::ZeroOp::create(builder, loc, srcBoxRef.getType()); } fir::runtime::genCopyOutAssign(builder, loc, destBoxRef, srcBoxRef); }; @@ -2436,8 +2438,8 @@ class ScalarExprLowering { // fir.box is absent. ExtValue actualArg = gen(expr); mlir::Value actualArgBase = fir::getBase(actualArg); - mlir::Value isPresent = builder.create( - loc, builder.getI1Type(), actualArgBase); + mlir::Value isPresent = fir::IsPresentOp::create( + builder, loc, builder.getI1Type(), actualArgBase); if (!mlir::isa(actualArgBase.getType())) return {actualArg, isPresent}; ExtValue safeToReadBox = @@ -2457,7 +2459,7 @@ class ScalarExprLowering { if (const fir::CharBoxValue *charBox = actualArg.getCharBox()) { mlir::Value len = charBox->getLen(); mlir::Value zero = builder.createIntegerConstant(loc, len.getType(), 0); - len = builder.create(loc, isPresent, len, zero); + len = mlir::arith::SelectOp::create(builder, loc, isPresent, len, zero); mlir::Value temp = builder.createTemporary(loc, type, /*name=*/{}, /*shape=*/{}, mlir::ValueRange{len}, @@ -2538,12 +2540,12 @@ class ScalarExprLowering { .genThen([&]() { fir::factory::genScalarAssignment(builder, loc, temp, actualArg); - builder.create(loc, fir::getBase(temp)); + fir::ResultOp::create(builder, loc, fir::getBase(temp)); }) .genElse([&]() { mlir::Value absent = - builder.create(loc, tempAddrTy); - builder.create(loc, absent); + fir::AbsentOp::create(builder, loc, tempAddrTy); + fir::ResultOp::create(builder, loc, absent); }) .getResults()[0]; return {fir::substBase(temp, selectAddr), isPresent}; @@ -2647,7 +2649,7 @@ class ScalarExprLowering { mlir::Value boxStorage = builder.createTemporary(loc, boxTy); mlir::Value nullBox = fir::factory::createUnallocatedBox( builder, loc, boxTy, /*nonDeferredParams=*/{}); - builder.create(loc, nullBox, boxStorage); + fir::StoreOp::create(builder, loc, nullBox, boxStorage); caller.placeInput(arg, boxStorage); continue; } @@ -2663,8 +2665,7 @@ class ScalarExprLowering { /*nonDeferredParams=*/mlir::ValueRange{}, /*mutableProperties=*/{}); Fortran::lower::associateMutableBox(converter, loc, pointer, *expr, - /*lbounds=*/std::nullopt, - stmtCtx); + /*lbounds=*/{}, stmtCtx); caller.placeInput(arg, irBox); continue; } @@ -2707,9 +2708,10 @@ class ScalarExprLowering { mlir::cast(funcTy.getResult(0)); mlir::Value ref = builder.createConvertWithVolatileCast( loc, builder.getRefType(boxTy.getEleTy()), x.getAddr()); - auto len = builder.create( - loc, builder.getCharacterLengthType()); - return builder.create(loc, boxTy, ref, len); + auto len = fir::UndefOp::create( + builder, loc, builder.getCharacterLengthType()); + return fir::EmboxCharOp::create(builder, loc, boxTy, ref, + len); } return helper.createEmbox(x); }, @@ -2759,10 +2761,10 @@ class ScalarExprLowering { mlir::Value box = builder.createBox(loc, argAddr); if (isPresentValue) { mlir::Value convertedBox = builder.createConvert(loc, argTy, box); - auto absent = builder.create(loc, argTy); - caller.placeInput(arg, - builder.create( - loc, *isPresentValue, convertedBox, absent)); + auto absent = fir::AbsentOp::create(builder, loc, argTy); + caller.placeInput( + arg, mlir::arith::SelectOp::create( + builder, loc, *isPresentValue, convertedBox, absent)); } else { caller.placeInput(arg, builder.createBox(loc, argAddr)); } @@ -2783,7 +2785,7 @@ class ScalarExprLowering { mlir::Value isAllocated = fir::factory::genIsAllocatedOrAssociatedTest(builder, loc, mutableBox); - auto absent = builder.create(loc, argTy); + auto absent = fir::AbsentOp::create(builder, loc, argTy); /// For now, assume it is not OK to pass the allocatable/pointer /// descriptor to a non pointer/allocatable dummy. That is a strict /// interpretation of 18.3.6 point 4 that stipulates the descriptor @@ -2802,14 +2804,15 @@ class ScalarExprLowering { box); } else if (mlir::isa(box.getType()) && fir::isPolymorphicType(argTy)) { - box = builder.create(loc, argTy, box, mlir::Value{}, - /*slice=*/mlir::Value{}); + box = fir::ReboxOp::create(builder, loc, argTy, box, mlir::Value{}, + /*slice=*/mlir::Value{}); } // Need the box types to be exactly similar for the selectOp. mlir::Value convertedBox = builder.createConvert(loc, argTy, box); - caller.placeInput(arg, builder.create( - loc, isAllocated, convertedBox, absent)); + caller.placeInput( + arg, mlir::arith::SelectOp::create(builder, loc, isAllocated, + convertedBox, absent)); } else { auto dynamicType = expr->GetType(); mlir::Value box; @@ -2831,12 +2834,12 @@ class ScalarExprLowering { .genThen([&]() { auto boxed = builder.createBox( loc, genBoxArg(*expr), fir::isPolymorphicType(argTy)); - builder.create(loc, boxed); + fir::ResultOp::create(builder, loc, boxed); }) .genElse([&]() { - auto absent = - builder.create(loc, argTy).getResult(); - builder.create(loc, absent); + auto absent = fir::AbsentOp::create(builder, loc, argTy) + .getResult(); + fir::ResultOp::create(builder, loc, absent); }) .getResults()[0]; } else { @@ -2868,19 +2871,19 @@ class ScalarExprLowering { loc, actualTy, box, mlir::Value{}, /*slice=*/mlir::Value{}) .getResult(); - builder.create(loc, rebox); + fir::ResultOp::create(builder, loc, rebox); }) .genElse([&]() { auto absent = - builder.create(loc, actualTy) + fir::AbsentOp::create(builder, loc, actualTy) .getResult(); - builder.create(loc, absent); + fir::ResultOp::create(builder, loc, absent); }) .getResults()[0]; } else { - box = builder.create(loc, actualTy, box, - mlir::Value{}, - /*slice=*/mlir::Value{}); + box = fir::ReboxOp::create(builder, loc, actualTy, box, + mlir::Value{}, + /*slice=*/mlir::Value{}); } } else if (Fortran::lower::isParentComponent(*expr)) { fir::ExtendedValue newExv = @@ -3133,12 +3136,12 @@ static void genScalarUserDefinedAssignmentCall(fir::FirOpBuilder &builder, if (argBaseType != fir::unwrapRefType(from.getType())) { // With logicals, it is possible that from is i1 here. if (fir::isa_ref_type(from.getType())) - from = builder.create(loc, from); + from = fir::LoadOp::create(builder, loc, from); from = builder.createConvert(loc, argBaseType, from); } if (!fir::isa_ref_type(from.getType())) { mlir::Value temp = builder.createTemporary(loc, argBaseType); - builder.create(loc, from, temp); + fir::StoreOp::create(builder, loc, from, temp); from = temp; } return builder.createConvert(loc, argType, from); @@ -3148,7 +3151,7 @@ static void genScalarUserDefinedAssignmentCall(fir::FirOpBuilder &builder, mlir::Type rhsType = func.getFunctionType().getInput(1); mlir::Value lhsArg = prepareUserDefinedArg(builder, loc, lhs, lhsType); mlir::Value rhsArg = prepareUserDefinedArg(builder, loc, rhs, rhsType); - builder.create(loc, func, mlir::ValueRange{lhsArg, rhsArg}); + fir::CallOp::create(builder, loc, func, mlir::ValueRange{lhsArg, rhsArg}); } /// Convert the result of a fir.array_modify to an ExtendedValue given the @@ -3188,17 +3191,17 @@ createDerivedArrayAmend(mlir::Location loc, fir::ArrayLoadOp destLoad, fir::factory::genRecordAssignment(builder, loc, destAcc, elementExv); } else { auto boxTy = fir::BoxType::get(eleTy); - auto toBox = builder.create(loc, boxTy, destAcc.getResult(), - mlir::Value{}, mlir::Value{}, - destLoad.getTypeparams()); - auto fromBox = builder.create( - loc, boxTy, fir::getBase(elementExv), mlir::Value{}, mlir::Value{}, - destLoad.getTypeparams()); + auto toBox = fir::EmboxOp::create(builder, loc, boxTy, destAcc.getResult(), + mlir::Value{}, mlir::Value{}, + destLoad.getTypeparams()); + auto fromBox = fir::EmboxOp::create( + builder, loc, boxTy, fir::getBase(elementExv), mlir::Value{}, + mlir::Value{}, destLoad.getTypeparams()); fir::factory::genRecordAssignment(builder, loc, fir::BoxValue(toBox), fir::BoxValue(fromBox)); } - return builder.create(loc, innerArg.getType(), innerArg, - destAcc); + return fir::ArrayAmendOp::create(builder, loc, innerArg.getType(), innerArg, + destAcc); } inline static fir::ArrayAmendOp @@ -3220,7 +3223,7 @@ createCharArrayAmend(mlir::Location loc, fir::FirOpBuilder &builder, helper.createAssign(fir::ExtendedValue{dstChar}, srcExv); // Mark this array element as amended. mlir::Type ty = innerArg.getType(); - auto amend = builder.create(loc, ty, innerArg, dstOp); + auto amend = fir::ArrayAmendOp::create(builder, loc, ty, innerArg, dstOp); return amend; } @@ -3236,7 +3239,7 @@ convertToArrayBoxValue(mlir::Location loc, fir::FirOpBuilder &builder, mlir::Type ty = fir::unwrapRefType(val.getType()); mlir::IndexType idxTy = builder.getIndexType(); auto seqTy = mlir::cast(ty); - auto undef = builder.create(loc, idxTy); + auto undef = fir::UndefOp::create(builder, loc, idxTy); llvm::SmallVector extents(seqTy.getDimension(), undef); if (fir::isa_char(seqTy.getEleTy())) return fir::CharArrayBoxValue(val, len ? len : undef, extents); @@ -3316,10 +3319,10 @@ class ArrayExprLowering { ExtValue exv = lowerArrayExpression(rhs); if (explicitSpaceIsActive()) { explicitSpace->finalizeContext(); - builder.create(loc, fir::getBase(exv)); + fir::ResultOp::create(builder, loc, fir::getBase(exv)); } else { - builder.create( - loc, destination, fir::getBase(exv), destination.getMemref(), + fir::ArrayMergeStoreOp::create( + builder, loc, destination, fir::getBase(exv), destination.getMemref(), destination.getSlice(), destination.getTypeparams()); } } @@ -3433,8 +3436,8 @@ class ArrayExprLowering { assert(destination && "destination must have been set"); ExtValue exv = lowerArrayExpression(rhsCC, destination.getType()); if (!explicitSpaceIsActive()) - builder.create( - loc, destination, fir::getBase(exv), destination.getMemref(), + fir::ArrayMergeStoreOp::create( + builder, loc, destination, fir::getBase(exv), destination.getMemref(), destination.getSlice(), destination.getTypeparams()); // destShape may originally be null, if rhs did not define a shape. // In this case the destShape is computed from lhs, and we may have @@ -3503,7 +3506,7 @@ class ArrayExprLowering { lengthParams, assignToStorage); if (explicitSpaceIsActive()) { explicitSpace->finalizeContext(); - builder.create(loc, fir::getBase(realloc.newValue)); + fir::ResultOp::create(builder, loc, fir::getBase(realloc.newValue)); } fir::factory::finalizeRealloc(builder, loc, mutableBox, lbounds, takeLboundsIfRealloc, realloc); @@ -3548,9 +3551,9 @@ class ArrayExprLowering { mlir::Value tempRes = dest.getMemref(); fir::FirOpBuilder &builder = converter.getFirOpBuilder(); mlir::Location loc = converter.getCurrentLocation(); - builder.create(loc, dest, fir::getBase(loopRes), - tempRes, dest.getSlice(), - dest.getTypeparams()); + fir::ArrayMergeStoreOp::create(builder, loc, dest, fir::getBase(loopRes), + tempRes, dest.getSlice(), + dest.getTypeparams()); auto arrTy = mlir::cast( fir::dyn_cast_ptrEleTy(tempRes.getType())); @@ -3596,25 +3599,26 @@ class ArrayExprLowering { // as there isn't any necessity for it. ccLoadDest = [=](llvm::ArrayRef shape) -> fir::ArrayLoadOp { mlir::Value one = builder.createIntegerConstant(loc, i32Ty, 1); - auto var = builder.create( - loc, builder.getRefType(hdrTy.getType(1)), header, one); - auto load = builder.create(loc, var); + auto var = fir::CoordinateOp::create( + builder, loc, builder.getRefType(hdrTy.getType(1)), header, one); + auto load = fir::LoadOp::create(builder, loc, var); mlir::Type eleTy = fir::unwrapSequenceType(fir::unwrapRefType(load.getType())); auto seqTy = fir::SequenceType::get(eleTy, shape.size()); mlir::Value castTo = builder.createConvert(loc, fir::HeapType::get(seqTy), load); mlir::Value shapeOp = builder.genShape(loc, shape); - return builder.create( - loc, seqTy, castTo, shapeOp, /*slice=*/mlir::Value{}, std::nullopt); + return fir::ArrayLoadOp::create(builder, loc, seqTy, castTo, shapeOp, + /*slice=*/mlir::Value{}, + mlir::ValueRange{}); }; // Custom lowering of the element store to deal with the extra indirection // to the lazy allocated buffer. ccStoreToDest = [=](IterSpace iters) { mlir::Value one = builder.createIntegerConstant(loc, i32Ty, 1); - auto var = builder.create( - loc, builder.getRefType(hdrTy.getType(1)), header, one); - auto load = builder.create(loc, var); + auto var = fir::CoordinateOp::create( + builder, loc, builder.getRefType(hdrTy.getType(1)), header, one); + auto load = fir::LoadOp::create(builder, loc, var); mlir::Type eleTy = fir::unwrapSequenceType(fir::unwrapRefType(load.getType())); auto seqTy = fir::SequenceType::get(eleTy, iters.iterVec().size()); @@ -3623,12 +3627,12 @@ class ArrayExprLowering { mlir::Value shape = builder.genShape(loc, genIterationShape()); llvm::SmallVector indices = fir::factory::originateIndices( loc, builder, castTo.getType(), shape, iters.iterVec()); - auto eleAddr = builder.create( - loc, builder.getRefType(eleTy), castTo, shape, + auto eleAddr = fir::ArrayCoorOp::create( + builder, loc, builder.getRefType(eleTy), castTo, shape, /*slice=*/mlir::Value{}, indices, destination.getTypeparams()); mlir::Value eleVal = builder.createConvert(loc, eleTy, iters.getElement()); - builder.create(loc, eleVal, eleAddr); + fir::StoreOp::create(builder, loc, eleVal, eleAddr); return iters.innerArgument(); }; @@ -3684,10 +3688,10 @@ class ArrayExprLowering { auto exv = lowerArrayExpression(rhs); if (explicitSpaceIsActive()) { explicitSpace->finalizeContext(); - builder.create(loc, fir::getBase(exv)); + fir::ResultOp::create(builder, loc, fir::getBase(exv)); } else { - builder.create( - loc, destination, fir::getBase(exv), destination.getMemref(), + fir::ArrayMergeStoreOp::create( + builder, loc, destination, fir::getBase(exv), destination.getMemref(), destination.getSlice(), destination.getTypeparams()); } } @@ -3766,7 +3770,7 @@ class ArrayExprLowering { std::size_t offset = explicitSpace->argPosition(oldInnerArg); explicitSpace->setInnerArg(offset, fir::getBase(lexv)); finalizeElementCtx(); - builder.create(loc, fir::getBase(lexv)); + fir::ResultOp::create(builder, loc, fir::getBase(lexv)); }; if (mlir::Operation *defOp = fir::getBase(lexv).getDefiningOp()) { llvm::TypeSwitch(defOp) @@ -3836,7 +3840,7 @@ class ArrayExprLowering { // 5). Thread the array value updated forward. if (!isIllFormedLHS) { finalizeElementCtx(); - builder.create(getLoc(), fir::getBase(lexv)); + fir::ResultOp::create(builder, getLoc(), fir::getBase(lexv)); } return lexv; } @@ -3979,7 +3983,7 @@ class ArrayExprLowering { if (auto origEleTy = fir::dyn_cast_ptrEleTy(origVal.getType())) if (mlir::isa(origEleTy)) { // If origVal is a box variable, load it so it is in the value domain. - origVal = builder.create(loc, origVal); + origVal = fir::LoadOp::create(builder, loc, origVal); } if (mlir::isa(origVal.getType()) && !mlir::isa(eleTy)) { @@ -3998,7 +4002,7 @@ class ArrayExprLowering { TODO(loc, "TARGET of pointer assignment with runtime size/shape"); auto memrefTy = fir::boxMemRefType(mlir::cast(eleTy)); auto castTo = builder.createConvert(loc, memrefTy, origVal); - origVal = builder.create(loc, eleTy, castTo); + origVal = fir::EmboxOp::create(builder, loc, eleTy, castTo); } mlir::Value val = builder.convertWithSemantics(loc, eleTy, origVal); if (isBoundsSpec()) { @@ -4007,9 +4011,9 @@ class ArrayExprLowering { if (lbs.size() > 0) { // Rebox the value with user-specified shift. auto shiftTy = fir::ShiftType::get(eleTy.getContext(), lbs.size()); - mlir::Value shiftOp = builder.create(loc, shiftTy, lbs); - val = builder.create(loc, eleTy, val, shiftOp, - mlir::Value{}); + mlir::Value shiftOp = fir::ShiftOp::create(builder, loc, shiftTy, lbs); + val = fir::ReboxOp::create(builder, loc, eleTy, val, shiftOp, + mlir::Value{}); } } else if (isBoundsRemap()) { assert(lbounds.has_value()); @@ -4020,9 +4024,9 @@ class ArrayExprLowering { auto shapeShiftArgs = flatZip(lbs, *ubounds); auto shapeTy = fir::ShapeShiftType::get(eleTy.getContext(), lbs.size()); mlir::Value shapeShift = - builder.create(loc, shapeTy, shapeShiftArgs); - val = builder.create(loc, eleTy, val, shapeShift, - mlir::Value{}); + fir::ShapeShiftOp::create(builder, loc, shapeTy, shapeShiftArgs); + val = fir::ReboxOp::create(builder, loc, eleTy, val, shapeShift, + mlir::Value{}); } } return val; @@ -4045,8 +4049,8 @@ class ArrayExprLowering { // memory into the destination array. mlir::Type resRefTy = builder.getRefType(eleTy); // Get a reference to the array element to be amended. - auto arrayOp = builder.create( - loc, resRefTy, innerArg, iterSpace.iterVec(), + auto arrayOp = fir::ArrayAccessOp::create( + builder, loc, resRefTy, innerArg, iterSpace.iterVec(), fir::factory::getTypeParams(loc, builder, destination)); if (auto charTy = mlir::dyn_cast(eleTy)) { llvm::SmallVector substringBounds; @@ -4067,9 +4071,9 @@ class ArrayExprLowering { } // By value semantics. The element is being assigned by value. auto ele = convertElementForUpdate(loc, eleTy, fir::getBase(exv)); - auto update = builder.create( - loc, arrTy, innerArg, ele, iterSpace.iterVec(), - destination.getTypeparams()); + auto update = fir::ArrayUpdateOp::create(builder, loc, arrTy, innerArg, + ele, iterSpace.iterVec(), + destination.getTypeparams()); return abstractArrayExtValue(update); }; } @@ -4094,7 +4098,7 @@ class ArrayExprLowering { : defaultStoreToDestination(/*substring=*/nullptr); mlir::Value updVal = fir::getBase(lambda(iterSpace)); finalizeElementCtx(); - builder.create(loc, updVal); + fir::ResultOp::create(builder, loc, updVal); builder.restoreInsertionPoint(insPt); return abstractArrayExtValue(iterSpace.outerResult()); } @@ -4208,7 +4212,7 @@ class ArrayExprLowering { auto addr = builder->create(loc, eleRefTy, tmp, shape, /*slice=*/mlir::Value{}, indices, - /*typeParams=*/std::nullopt); + /*typeParams=*/mlir::ValueRange{}); auto load = builder->create(loc, addr); return builder->createConvert(loc, i1Ty, load); }; @@ -4247,31 +4251,34 @@ class ArrayExprLowering { // Compute the dynamic position into the header. llvm::SmallVector offsets; for (auto doLoop : loopStack[i]) { - auto m = builder.create( - loc, doLoop.getInductionVar(), doLoop.getLowerBound()); - auto n = builder.create(loc, m, doLoop.getStep()); + auto m = mlir::arith::SubIOp::create( + builder, loc, doLoop.getInductionVar(), doLoop.getLowerBound()); + auto n = + mlir::arith::DivSIOp::create(builder, loc, m, doLoop.getStep()); mlir::Value one = builder.createIntegerConstant(loc, n.getType(), 1); - offsets.push_back(builder.create(loc, n, one)); + offsets.push_back(mlir::arith::AddIOp::create(builder, loc, n, one)); } mlir::IntegerType i32Ty = builder.getIntegerType(32); mlir::Value uno = builder.createIntegerConstant(loc, i32Ty, 1); mlir::Type coorTy = builder.getRefType(raggedTy.getType(1)); - auto hdOff = builder.create(loc, coorTy, header, uno); + auto hdOff = fir::CoordinateOp::create(builder, loc, coorTy, header, uno); auto toTy = fir::SequenceType::get(raggedTy, offsets.size()); mlir::Type toRefTy = builder.getRefType(toTy); - auto ldHdr = builder.create(loc, hdOff); + auto ldHdr = fir::LoadOp::create(builder, loc, hdOff); mlir::Value hdArr = builder.createConvert(loc, toRefTy, ldHdr); auto shapeOp = builder.genShape(loc, extents); - header = builder.create( - loc, builder.getRefType(raggedTy), hdArr, shapeOp, + header = fir::ArrayCoorOp::create( + builder, loc, builder.getRefType(raggedTy), hdArr, shapeOp, /*slice=*/mlir::Value{}, offsets, /*typeparams=*/mlir::ValueRange{}); - auto hdrVar = builder.create(loc, coorTy, header, uno); - auto inVar = builder.create(loc, hdrVar); + auto hdrVar = + fir::CoordinateOp::create(builder, loc, coorTy, header, uno); + auto inVar = fir::LoadOp::create(builder, loc, hdrVar); mlir::Value two = builder.createIntegerConstant(loc, i32Ty, 2); mlir::Type coorTy2 = builder.getRefType(raggedTy.getType(2)); - auto hdrSh = builder.create(loc, coorTy2, header, two); - auto shapePtr = builder.create(loc, hdrSh); + auto hdrSh = + fir::CoordinateOp::create(builder, loc, coorTy2, header, two); + auto shapePtr = fir::LoadOp::create(builder, loc, hdrSh); // Replace the binding. implicitSpace->rebind(expr, genMaskAccess(inVar, shapePtr)); if (i < depth - 1) @@ -4301,7 +4308,7 @@ class ArrayExprLowering { Fortran::lower::createLazyArrayTempValue(converter, *e, header, symMap, stmtCtx); // Close the explicit loops. - builder.create(loc, explicitSpace->getInnerArgs()); + fir::ResultOp::create(builder, loc, explicitSpace->getInnerArgs()); builder.setInsertionPointAfter(explicitSpace->getOuterLoop()); // Open a new copy of the explicit loop nest. explicitSpace->genLoopNest(); @@ -4327,9 +4334,10 @@ class ArrayExprLowering { fir::factory::getRaggedArrayHeaderType(builder); mlir::IntegerType i32Ty = builder.getIntegerType(32); mlir::Value one = builder.createIntegerConstant(loc, i32Ty, 1); - auto coor1 = builder.create( - loc, builder.getRefType(raggedTy.getType(1)), header, one); - auto db = builder.create(loc, coor1); + auto coor1 = fir::CoordinateOp::create( + builder, loc, builder.getRefType(raggedTy.getType(1)), header, + one); + auto db = fir::LoadOp::create(builder, loc, coor1); mlir::Type eleTy = fir::unwrapSequenceType(fir::unwrapRefType(db.getType())); mlir::Type buffTy = @@ -4338,17 +4346,18 @@ class ArrayExprLowering { mlir::Value buff = builder.createConvert(loc, buffTy, db); mlir::Value two = builder.createIntegerConstant(loc, i32Ty, 2); - auto coor2 = builder.create( - loc, builder.getRefType(raggedTy.getType(2)), header, two); - auto shBuff = builder.create(loc, coor2); + auto coor2 = fir::CoordinateOp::create( + builder, loc, builder.getRefType(raggedTy.getType(2)), header, + two); + auto shBuff = fir::LoadOp::create(builder, loc, coor2); mlir::IntegerType i64Ty = builder.getIntegerType(64); mlir::IndexType idxTy = builder.getIndexType(); llvm::SmallVector extents; for (std::remove_const_t i = 0; i < rank; ++i) { mlir::Value off = builder.createIntegerConstant(loc, i32Ty, i); - auto coor = builder.create( - loc, builder.getRefType(i64Ty), shBuff, off); - auto ldExt = builder.create(loc, coor); + auto coor = fir::CoordinateOp::create( + builder, loc, builder.getRefType(i64Ty), shBuff, off); + auto ldExt = fir::LoadOp::create(builder, loc, coor); extents.push_back(builder.createConvert(loc, idxTy, ldExt)); } if (destShape.empty()) @@ -4376,7 +4385,7 @@ class ArrayExprLowering { // run from 0 to `extent - 1` inclusive. for (auto extent : shape) loopUppers.push_back( - builder.create(loc, extent, one)); + mlir::arith::SubIOp::create(builder, loc, extent, one)); // Iteration space is created with outermost columns, innermost rows llvm::SmallVector loops; @@ -4391,16 +4400,16 @@ class ArrayExprLowering { } fir::DoLoopOp loop; if (innerArg) { - loop = builder.create( - loc, zero, i.value(), one, isUnordered(), + loop = fir::DoLoopOp::create( + builder, loc, zero, i.value(), one, isUnordered(), /*finalCount=*/false, mlir::ValueRange{innerArg}); innerArg = loop.getRegionIterArgs().front(); if (explicitSpaceIsActive()) explicitSpace->setInnerArg(0, innerArg); } else { - loop = builder.create(loc, zero, i.value(), one, - isUnordered(), - /*finalCount=*/false); + loop = fir::DoLoopOp::create(builder, loc, zero, i.value(), one, + isUnordered(), + /*finalCount=*/false); } ivars.push_back(loop.getInductionVar()); loops.push_back(loop); @@ -4410,7 +4419,7 @@ class ArrayExprLowering { for (std::remove_const_t i = 0; i + 1 < loopDepth; ++i) { builder.setInsertionPointToEnd(loops[i].getBody()); - builder.create(loc, loops[i + 1].getResult(0)); + fir::ResultOp::create(builder, loc, loops[i + 1].getResult(0)); } // Move insertion point to the start of the innermost loop in the nest. @@ -4468,21 +4477,23 @@ class ArrayExprLowering { implicitSpace->getMasks()) { const std::size_t size = maskExprs.size() - 1; auto genFalseBlock = [&](const auto *e, auto &&cond) { - auto ifOp = builder.create( - loc, mlir::TypeRange{innerArg.getType()}, fir::getBase(cond), - /*withElseRegion=*/true); - builder.create(loc, ifOp.getResult(0)); + auto ifOp = fir::IfOp::create(builder, loc, + mlir::TypeRange{innerArg.getType()}, + fir::getBase(cond), + /*withElseRegion=*/true); + fir::ResultOp::create(builder, loc, ifOp.getResult(0)); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); - builder.create(loc, innerArg); + fir::ResultOp::create(builder, loc, innerArg); builder.setInsertionPointToStart(&ifOp.getElseRegion().front()); }; auto genTrueBlock = [&](const auto *e, auto &&cond) { - auto ifOp = builder.create( - loc, mlir::TypeRange{innerArg.getType()}, fir::getBase(cond), - /*withElseRegion=*/true); - builder.create(loc, ifOp.getResult(0)); + auto ifOp = fir::IfOp::create(builder, loc, + mlir::TypeRange{innerArg.getType()}, + fir::getBase(cond), + /*withElseRegion=*/true); + fir::ResultOp::create(builder, loc, ifOp.getResult(0)); builder.setInsertionPointToStart(&ifOp.getElseRegion().front()); - builder.create(loc, innerArg); + fir::ResultOp::create(builder, loc, innerArg); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); }; for (std::remove_const_t i = 0; i < size; ++i) @@ -4523,17 +4534,18 @@ class ArrayExprLowering { fir::isRecordWithAllocatableMember(eleTy)) TODO(loc, "creating an array temp where the element type has " "allocatable members"); - mlir::Value temp = !seqTy.hasDynamicExtents() - ? builder.create(loc, type) - : builder.create( - loc, type, ".array.expr", std::nullopt, shape); + mlir::Value temp = + !seqTy.hasDynamicExtents() + ? fir::AllocMemOp::create(builder, loc, type) + : fir::AllocMemOp::create(builder, loc, type, ".array.expr", + mlir::ValueRange{}, shape); fir::FirOpBuilder *bldr = &converter.getFirOpBuilder(); stmtCtx.attachCleanup( [bldr, loc, temp]() { bldr->create(loc, temp); }); mlir::Value shapeOp = genShapeOp(shape); - return builder.create(loc, seqTy, temp, shapeOp, - /*slice=*/mlir::Value{}, - std::nullopt); + return fir::ArrayLoadOp::create(builder, loc, seqTy, temp, shapeOp, + /*slice=*/mlir::Value{}, + mlir::ValueRange{}); } static fir::ShapeOp genShapeOp(mlir::Location loc, fir::FirOpBuilder &builder, @@ -4542,7 +4554,7 @@ class ArrayExprLowering { llvm::SmallVector idxShape; for (auto s : shape) idxShape.push_back(builder.createConvert(loc, idxTy, s)); - return builder.create(loc, idxShape); + return fir::ShapeOp::create(builder, loc, idxShape); } fir::ShapeOp genShapeOp(llvm::ArrayRef shape) { @@ -4790,7 +4802,7 @@ class ArrayExprLowering { mlir::Type argTy = callSiteType.getInput(arg.firArgument); if (!actual) { // Optional dummy argument for which there is no actual argument. - auto absent = builder.create(loc, argTy); + auto absent = fir::AbsentOp::create(builder, loc, argTy); operands.emplace_back([=](IterSpace) { return absent; }); continue; } @@ -4823,7 +4835,7 @@ class ArrayExprLowering { builder.createTemporary(loc, val.getType(), llvm::ArrayRef{ fir::getAdaptToByRefAttr(builder)}); - builder.create(loc, val, temp); + fir::StoreOp::create(builder, loc, val, temp); operands.emplace_back( [=](IterSpace iters) -> ExtValue { return temp; }); } @@ -4882,14 +4894,14 @@ class ArrayExprLowering { fir::dyn_cast_ptrOrBoxEleTy(fir::getBase(exv).getType()); mlir::Type innerTy = fir::unwrapSequenceType(baseTy); operands.emplace_back([=](IterSpace iters) -> ExtValue { - mlir::Value coord = builder.create( - loc, fir::ReferenceType::get(innerTy), fir::getBase(exv), - iters.iterVec()); + mlir::Value coord = fir::CoordinateOp::create( + builder, loc, fir::ReferenceType::get(innerTy), + fir::getBase(exv), iters.iterVec()); mlir::Value empty; mlir::ValueRange emptyRange; - return builder.create( - loc, fir::ClassType::get(innerTy), coord, empty, empty, - emptyRange, sourceBox); + return fir::EmboxOp::create(builder, loc, + fir::ClassType::get(innerTy), coord, + empty, empty, emptyRange, sourceBox); }); } else { ExtValue exv = asScalarRef(*expr); @@ -4902,9 +4914,9 @@ class ArrayExprLowering { operands.emplace_back([=](IterSpace iters) -> ExtValue { mlir::Value empty; mlir::ValueRange emptyRange; - return builder.create( - loc, fir::ClassType::get(baseTy), fir::getBase(exv), empty, - empty, emptyRange); + return fir::EmboxOp::create( + builder, loc, fir::ClassType::get(baseTy), + fir::getBase(exv), empty, empty, emptyRange); }); } } @@ -5096,8 +5108,8 @@ class ArrayExprLowering { return exv.match( [&](const fir::CharBoxValue &cb) -> ExtValue { mlir::Value len = cb.getLen(); - auto mem = - builder.create(loc, toType, mlir::ValueRange{len}); + auto mem = fir::AllocaOp::create(builder, loc, toType, + mlir::ValueRange{len}); fir::CharBoxValue result(mem, len); fir::factory::CharacterExprHelper{builder, loc}.createAssign( ExtValue{result}, exv); @@ -5152,7 +5164,7 @@ class ArrayExprLowering { auto val = f(iters); mlir::Value base = fir::getBase(val); auto newBase = - builder.create(loc, base.getType(), base); + fir::NoReassocOp::create(builder, loc, base.getType(), base); return fir::substBase(val, newBase); }; } @@ -5169,10 +5181,10 @@ class ArrayExprLowering { if constexpr (CAT == Fortran::common::TypeCategory::Unsigned) { mlir::Value signless = builder.createConvert(loc, ty, val); mlir::Value neg = - builder.create(loc, zero, signless); + mlir::arith::SubIOp::create(builder, loc, zero, signless); return builder.createConvert(loc, val.getType(), neg); } - return builder.create(loc, zero, val); + return mlir::arith::SubIOp::create(builder, loc, zero, val); }; } template @@ -5191,7 +5203,7 @@ class ArrayExprLowering { mlir::Location loc = getLoc(); auto f = genarr(x.left()); return [=](IterSpace iters) -> ExtValue { - return builder.create(loc, fir::getBase(f(iters))); + return mlir::arith::NegFOp::create(builder, loc, fir::getBase(f(iters))); }; } template @@ -5200,7 +5212,7 @@ class ArrayExprLowering { mlir::Location loc = getLoc(); auto f = genarr(x.left()); return [=](IterSpace iters) -> ExtValue { - return builder.create(loc, fir::getBase(f(iters))); + return fir::NegcOp::create(builder, loc, fir::getBase(f(iters))); }; } @@ -5425,8 +5437,8 @@ class ArrayExprLowering { mlir::Location loc = getLoc(); mlir::Value lb = getLBound(x, dim, one); mlir::Value extent = fir::factory::readExtent(builder, loc, x, dim); - auto add = builder.create(loc, lb, extent); - return builder.create(loc, add, one); + auto add = mlir::arith::AddIOp::create(builder, loc, lb, extent); + return mlir::arith::SubIOp::create(builder, loc, add, one); } /// Return the extent of the boxed array `x` in dimesion `dim`. @@ -5468,11 +5480,11 @@ class ArrayExprLowering { if (destShape[0] != savedDestShape[dim]) { // Not the same, so choose the smaller value. mlir::Location loc = getLoc(); - auto cmp = builder.create( - loc, mlir::arith::CmpIPredicate::sgt, destShape[0], - savedDestShape[dim]); - auto sel = builder.create( - loc, cmp, savedDestShape[dim], destShape[0]); + auto cmp = mlir::arith::CmpIOp::create(builder, loc, + mlir::arith::CmpIPredicate::sgt, + destShape[0], savedDestShape[dim]); + auto sel = mlir::arith::SelectOp::create( + builder, loc, cmp, savedDestShape[dim], destShape[0]); savedDestShape[dim] = sel; destShape = savedDestShape; } @@ -5548,12 +5560,12 @@ class ArrayExprLowering { // FIXME: must use the lower bound of this component. auto arrLowerBound = atBase ? getLBound(arrayExv, subsIndex, one) : one; - auto initial = builder.create( - loc, lowerBound, arrLowerBound); - auto prod = builder.create( - loc, impliedIter, stride); - auto result = - builder.create(loc, initial, prod); + auto initial = mlir::arith::SubIOp::create( + builder, loc, lowerBound, arrLowerBound); + auto prod = mlir::arith::MulIOp::create( + builder, loc, impliedIter, stride); + auto result = mlir::arith::AddIOp::create(builder, loc, + initial, prod); newIters.setIndexValue(subsIndex, result); return newIters; }; @@ -5587,15 +5599,15 @@ class ArrayExprLowering { // using the base array's lower bound value. mlir::Value lb = fir::factory::readLowerBound( builder, loc, arrayExv, subsIndex, one); - auto origin = builder.create( - loc, idxTy, val, lb); + auto origin = mlir::arith::SubIOp::create(builder, loc, + idxTy, val, lb); newIters.setIndexValue(subsIndex, origin); return newIters; }; if (useTripsForSlice) { LLVM_ATTRIBUTE_UNUSED auto vectorSubscriptShape = getShape(arrayOperands.back()); - auto undef = builder.create(loc, idxTy); + auto undef = fir::UndefOp::create(builder, loc, idxTy); trips.push_back(undef); trips.push_back(undef); trips.push_back(undef); @@ -5613,7 +5625,7 @@ class ArrayExprLowering { // the array's declared rank. mlir::Value v = fir::getBase(asScalarArray(e)); trips.push_back(v); - auto undef = builder.create(loc, idxTy); + auto undef = fir::UndefOp::create(builder, loc, idxTy); trips.push_back(undef); trips.push_back(undef); auto currentPC = pc; @@ -5622,8 +5634,8 @@ class ArrayExprLowering { // Normalize `e` by subtracting the declared lbound. mlir::Value lb = fir::factory::readLowerBound( builder, loc, arrayExv, subsIndex, one); - mlir::Value ivAdj = - builder.create(loc, idxTy, iv, lb); + mlir::Value ivAdj = mlir::arith::SubIOp::create( + builder, loc, idxTy, iv, lb); // Add lbound adjusted value of `e` to the iteration vector // (except when creating a box because the iteration vector // is empty). @@ -5640,8 +5652,8 @@ class ArrayExprLowering { builder.createConvert(loc, idxTy, newValue); mlir::Value lb = fir::factory::readLowerBound( builder, loc, arrayExv, subsIndex, one); - result = builder.create(loc, idxTy, - result, lb); + result = mlir::arith::SubIOp::create(builder, loc, idxTy, + result, lb); pc = [=](IterSpace iters) { IterationSpace newIters = currentPC(iters); newIters.insertIndexValue(subsIndex, result); @@ -5670,7 +5682,7 @@ class ArrayExprLowering { auto seqType = mlir::cast(ty); for (auto extent : seqType.getShape()) { auto v = extent == fir::SequenceType::getUnknownExtent() - ? builder.create(loc, idxTy).getResult() + ? fir::UndefOp::create(builder, loc, idxTy).getResult() : builder.createIntegerConstant(loc, idxTy, extent); result.push_back(v); } @@ -5763,20 +5775,20 @@ class ArrayExprLowering { mlir::Value one = builder.createIntegerConstant(loc, substringBounds[0].getType(), 1); substringBounds[0] = - builder.create(loc, substringBounds[0], one); + mlir::arith::SubIOp::create(builder, loc, substringBounds[0], one); // Convert the upper bound to a length. mlir::Value cast = builder.createConvert(loc, iTy, substringBounds[1]); mlir::Value zero = builder.createIntegerConstant(loc, iTy, 0); auto size = - builder.create(loc, cast, substringBounds[0]); - auto cmp = builder.create( - loc, mlir::arith::CmpIPredicate::sgt, size, zero); + mlir::arith::SubIOp::create(builder, loc, cast, substringBounds[0]); + auto cmp = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::sgt, size, zero); // size = MAX(upper - (lower - 1), 0) substringBounds[1] = - builder.create(loc, cmp, size, zero); - slice = builder.create( - loc, padSlice(components.trips, shape), components.suffixComponents, - substringBounds); + mlir::arith::SelectOp::create(builder, loc, cmp, size, zero); + slice = fir::SliceOp::create( + builder, loc, padSlice(components.trips, shape), + components.suffixComponents, substringBounds); } else { slice = builder.createSlice(loc, extMemref, components.trips, components.suffixComponents); @@ -5826,7 +5838,7 @@ class ArrayExprLowering { } mlir::Value embox = mlir::isa(memref.getType()) - ? builder.create(loc, boxTy, memref, shape, slice) + ? fir::ReboxOp::create(builder, loc, boxTy, memref, shape, slice) .getResult() : builder .create(loc, boxTy, memref, shape, slice, @@ -5848,8 +5860,8 @@ class ArrayExprLowering { // ArrayCoorOp does not expect zero based indices. llvm::SmallVector indices = fir::factory::originateIndices( loc, builder, memref.getType(), shape, iters.iterVec()); - mlir::Value coor = builder.create( - loc, refEleTy, memref, shape, slice, indices, + mlir::Value coor = fir::ArrayCoorOp::create( + builder, loc, refEleTy, memref, shape, slice, indices, fir::getTypeParams(extMemref)); if (auto charTy = mlir::dyn_cast(eleTy)) { llvm::SmallVector substringBounds; @@ -5868,16 +5880,17 @@ class ArrayExprLowering { builder, loc, extMemref, coor, slice); }; } - auto arrLoad = builder.create( - loc, arrTy, memref, shape, slice, fir::getTypeParams(extMemref)); + auto arrLoad = + fir::ArrayLoadOp::create(builder, loc, arrTy, memref, shape, slice, + fir::getTypeParams(extMemref)); if (CrayPtr) { mlir::Type ptrTy = CrayPtr.getType(); mlir::Value cnvrt = Fortran::lower::addCrayPointerInst( loc, builder, CrayPtr, ptrTy, memref.getType()); - auto addr = builder.create(loc, cnvrt); - arrLoad = builder.create(loc, arrTy, addr, shape, slice, - fir::getTypeParams(extMemref)); + auto addr = fir::LoadOp::create(builder, loc, cnvrt); + arrLoad = fir::ArrayLoadOp::create(builder, loc, arrTy, addr, shape, + slice, fir::getTypeParams(extMemref)); } mlir::Value arrLd = arrLoad.getResult(); @@ -5905,9 +5918,9 @@ class ArrayExprLowering { mlir::Type eleTy = fir::applyPathToType(resTy, iters.iterVec()); mlir::Type refEleTy = fir::isa_ref_type(eleTy) ? eleTy : builder.getRefType(eleTy); - auto arrModify = builder.create( - loc, mlir::TypeRange{refEleTy, resTy}, innerArg, iters.iterVec(), - destination.getTypeparams()); + auto arrModify = fir::ArrayModifyOp::create( + builder, loc, mlir::TypeRange{refEleTy, resTy}, innerArg, + iters.iterVec(), destination.getTypeparams()); return abstractArrayExtValue(arrModify.getResult(1)); }; } @@ -5931,17 +5944,17 @@ class ArrayExprLowering { mlir::Type eleTy = fir::applyPathToType(arrTy, iters.iterVec()); if (isAdjustedArrayElementType(eleTy)) { mlir::Type eleRefTy = builder.getRefType(eleTy); - base = builder.create( - loc, eleRefTy, arrLd, iters.iterVec(), arrLdTypeParams); + base = fir::ArrayAccessOp::create(builder, loc, eleRefTy, arrLd, + iters.iterVec(), arrLdTypeParams); } else { - base = builder.create( - loc, eleTy, arrLd, iters.iterVec(), arrLdTypeParams); + base = fir::ArrayFetchOp::create(builder, loc, eleTy, arrLd, + iters.iterVec(), arrLdTypeParams); } mlir::Value temp = builder.createTemporary(loc, base.getType(), llvm::ArrayRef{ fir::getAdaptToByRefAttr(builder)}); - builder.create(loc, base, temp); + fir::StoreOp::create(builder, loc, base, temp); return fir::factory::arraySectionElementToExtendedValue( builder, loc, extMemref, temp, slice); }; @@ -5952,8 +5965,8 @@ class ArrayExprLowering { mlir::Type eleTy = fir::applyPathToType(arrTy, iters.iterVec()); if (isAdjustedArrayElementType(eleTy)) { mlir::Type eleRefTy = builder.getRefType(eleTy); - mlir::Value arrayOp = builder.create( - loc, eleRefTy, arrLd, iters.iterVec(), arrLdTypeParams); + mlir::Value arrayOp = fir::ArrayAccessOp::create( + builder, loc, eleRefTy, arrLd, iters.iterVec(), arrLdTypeParams); if (auto charTy = mlir::dyn_cast(eleTy)) { llvm::SmallVector substringBounds; populateBounds(substringBounds, components.substring); @@ -5968,8 +5981,8 @@ class ArrayExprLowering { return fir::factory::arraySectionElementToExtendedValue( builder, loc, extMemref, arrayOp, slice); } - auto arrFetch = builder.create( - loc, eleTy, arrLd, iters.iterVec(), arrLdTypeParams); + auto arrFetch = fir::ArrayFetchOp::create( + builder, loc, eleTy, arrLd, iters.iterVec(), arrLdTypeParams); return fir::factory::arraySectionElementToExtendedValue( builder, loc, extMemref, arrFetch, slice); }; @@ -6008,8 +6021,8 @@ class ArrayExprLowering { mlir::Value memref = fir::getBase(exv); mlir::Value shape = builder.createShape(loc, exv); mlir::Value noSlice; - auto arrLoad = builder.create( - loc, arrType, memref, shape, noSlice, fir::getTypeParams(exv)); + auto arrLoad = fir::ArrayLoadOp::create( + builder, loc, arrType, memref, shape, noSlice, fir::getTypeParams(exv)); mlir::Operation::operand_range arrLdTypeParams = arrLoad.getTypeparams(); mlir::Value arrLd = arrLoad.getResult(); // Mark the load to tell later passes it is unsafe to use this array_load @@ -6024,8 +6037,8 @@ class ArrayExprLowering { // By value semantics. auto cc = [=](IterSpace iters) -> ExtValue { - auto arrFetch = builder.create( - loc, eleType, arrLd, iters.iterVec(), arrLdTypeParams); + auto arrFetch = fir::ArrayFetchOp::create( + builder, loc, eleType, arrLd, iters.iterVec(), arrLdTypeParams); return fir::factory::arraySectionElementToExtendedValue( builder, loc, exv, arrFetch, noSlice); }; @@ -6063,12 +6076,12 @@ class ArrayExprLowering { .genIfOp(loc, {eleType}, isPresent, /*withElseRegion=*/true) .genThen([&]() { - builder.create(loc, fir::getBase(cc(iters))); + fir::ResultOp::create(builder, loc, fir::getBase(cc(iters))); }) .genElse([&]() { mlir::Value zero = fir::factory::createZeroValue(builder, loc, eleType); - builder.create(loc, zero); + fir::ResultOp::create(builder, loc, zero); }) .getResults()[0]; return elementValue; @@ -6177,8 +6190,8 @@ class ArrayExprLowering { mlir::Type eleRefTy = builder.getRefType(eleTy); mlir::Type resRefTy = builder.getRefType(resTy); mlir::Value nullPtr = builder.createNullConstant(loc, resRefTy); - auto offset = builder.create( - loc, eleRefTy, nullPtr, mlir::ValueRange{multiplier}); + auto offset = fir::CoordinateOp::create(builder, loc, eleRefTy, nullPtr, + mlir::ValueRange{multiplier}); return builder.createConvert(loc, idxTy, offset); } @@ -6186,14 +6199,14 @@ class ArrayExprLowering { mlir::FunctionType memcpyType() { auto ptrTy = mlir::LLVM::LLVMPointerType::get(builder.getContext()); llvm::SmallVector args = {ptrTy, ptrTy, builder.getI64Type()}; - return mlir::FunctionType::get(builder.getContext(), args, std::nullopt); + return mlir::FunctionType::get(builder.getContext(), args, {}); } /// Create a call to the LLVM memcpy intrinsic. void createCallMemcpy(llvm::ArrayRef args, bool isVolatile) { mlir::Location loc = getLoc(); - builder.create(loc, args[0], args[1], args[2], - isVolatile); + mlir::LLVM::MemcpyOp::create(builder, loc, args[0], args[1], args[2], + isVolatile); } // Construct code to check for a buffer overrun and realloc the buffer when @@ -6203,32 +6216,33 @@ class ArrayExprLowering { mlir::Value eleSz) { mlir::Location loc = getLoc(); mlir::func::FuncOp reallocFunc = fir::factory::getRealloc(builder); - auto cond = builder.create( - loc, mlir::arith::CmpIPredicate::sle, bufferSize, needed); - auto ifOp = builder.create(loc, mem.getType(), cond, - /*withElseRegion=*/true); + auto cond = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::sle, bufferSize, needed); + auto ifOp = fir::IfOp::create(builder, loc, mem.getType(), cond, + /*withElseRegion=*/true); auto insPt = builder.saveInsertionPoint(); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); // Not enough space, resize the buffer. mlir::IndexType idxTy = builder.getIndexType(); mlir::Value two = builder.createIntegerConstant(loc, idxTy, 2); - auto newSz = builder.create(loc, needed, two); - builder.create(loc, newSz, buffSize); - mlir::Value byteSz = builder.create(loc, newSz, eleSz); + auto newSz = mlir::arith::MulIOp::create(builder, loc, needed, two); + fir::StoreOp::create(builder, loc, newSz, buffSize); + mlir::Value byteSz = + mlir::arith::MulIOp::create(builder, loc, newSz, eleSz); mlir::SymbolRefAttr funcSymAttr = builder.getSymbolRefAttr(reallocFunc.getName()); mlir::FunctionType funcTy = reallocFunc.getFunctionType(); - auto newMem = builder.create( - loc, funcSymAttr, funcTy.getResults(), + auto newMem = fir::CallOp::create( + builder, loc, funcSymAttr, funcTy.getResults(), llvm::ArrayRef{ builder.createConvert(loc, funcTy.getInputs()[0], mem), builder.createConvert(loc, funcTy.getInputs()[1], byteSz)}); mlir::Value castNewMem = builder.createConvert(loc, mem.getType(), newMem.getResult(0)); - builder.create(loc, castNewMem); + fir::ResultOp::create(builder, loc, castNewMem); builder.setInsertionPointToStart(&ifOp.getElseRegion().front()); // Otherwise, just forward the buffer. - builder.create(loc, mem); + fir::ResultOp::create(builder, loc, mem); builder.restoreInsertionPoint(insPt); return ifOp.getResult(0); } @@ -6240,8 +6254,8 @@ class ArrayExprLowering { mlir::Value eleSz, mlir::Type eleTy, mlir::Type eleRefTy, mlir::Type resTy) { mlir::Location loc = getLoc(); - auto off = builder.create(loc, buffPos); - auto limit = builder.create(loc, buffSize); + auto off = fir::LoadOp::create(builder, loc, buffPos); + auto limit = fir::LoadOp::create(builder, loc, buffSize); mlir::IndexType idxTy = builder.getIndexType(); mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1); @@ -6259,7 +6273,7 @@ class ArrayExprLowering { mlir::Value length = fir::getLen(exv); if (!length) fir::emitFatalError(loc, "result is not boxed character"); - eleSz = builder.create(loc, bytes, length); + eleSz = mlir::arith::MulIOp::create(builder, loc, bytes, length); } else { TODO(loc, "PDT size"); // Will call the PDT's size function with the type parameters. @@ -6278,13 +6292,13 @@ class ArrayExprLowering { refTy = builder.getRefType(chTy); mlir::Type toTy = builder.getRefType(builder.getVarLenSeqTy(chTy)); buff = builder.createConvert(loc, toTy, buff); - off = builder.create(loc, off, eleSz); + off = mlir::arith::MulIOp::create(builder, loc, off, eleSz); } else { TODO(loc, "PDT offset"); } } - auto coor = builder.create(loc, refTy, buff, - mlir::ValueRange{off}); + auto coor = fir::CoordinateOp::create(builder, loc, refTy, buff, + mlir::ValueRange{off}); return builder.createConvert(loc, eleRefTy, coor); }; @@ -6293,15 +6307,15 @@ class ArrayExprLowering { // Compute the array size. mlir::Value arrSz = one; for (auto ext : v.getExtents()) - arrSz = builder.create(loc, arrSz, ext); + arrSz = mlir::arith::MulIOp::create(builder, loc, arrSz, ext); // Grow the buffer as needed. - auto endOff = builder.create(loc, off, arrSz); + auto endOff = mlir::arith::AddIOp::create(builder, loc, off, arrSz); mem = growBuffer(mem, endOff, limit, buffSize, eleSz); // Copy the elements to the buffer. mlir::Value byteSz = - builder.create(loc, arrSz, eleSz); + mlir::arith::MulIOp::create(builder, loc, arrSz, eleSz); auto buff = builder.createConvert(loc, fir::HeapType::get(resTy), mem); mlir::Value buffi = computeCoordinate(buff, off); llvm::SmallVector args = fir::runtime::createArguments( @@ -6310,13 +6324,13 @@ class ArrayExprLowering { createCallMemcpy(args, isVolatile); // Save the incremented buffer position. - builder.create(loc, endOff, buffPos); + fir::StoreOp::create(builder, loc, endOff, buffPos); }; // Copy a trivial scalar value into the buffer. auto doTrivialScalar = [&](const ExtValue &v, mlir::Value len = {}) { // Increment the buffer position. - auto plusOne = builder.create(loc, off, one); + auto plusOne = mlir::arith::AddIOp::create(builder, loc, off, one); // Grow the buffer as needed. mem = growBuffer(mem, plusOne, limit, buffSize, eleSz); @@ -6324,8 +6338,8 @@ class ArrayExprLowering { // Store the element in the buffer. mlir::Value buff = builder.createConvert(loc, fir::HeapType::get(resTy), mem); - auto buffi = builder.create(loc, eleRefTy, buff, - mlir::ValueRange{off}); + auto buffi = fir::CoordinateOp::create(builder, loc, eleRefTy, buff, + mlir::ValueRange{off}); fir::factory::genScalarAssignment( builder, loc, [&]() -> ExtValue { @@ -6334,7 +6348,7 @@ class ArrayExprLowering { return buffi; }(), v); - builder.create(loc, plusOne, buffPos); + fir::StoreOp::create(builder, loc, plusOne, buffPos); }; // Copy the value. @@ -6346,7 +6360,7 @@ class ArrayExprLowering { doTrivialScalar(exv, eleSz); } else { // Increment the buffer position. - auto plusOne = builder.create(loc, off, one); + auto plusOne = mlir::arith::AddIOp::create(builder, loc, off, one); // Grow the buffer as needed. mem = growBuffer(mem, plusOne, limit, buffSize, eleSz); @@ -6361,7 +6375,7 @@ class ArrayExprLowering { fir::isa_volatile_type(v.getAddr().getType()); createCallMemcpy(args, isVolatile); - builder.create(loc, plusOne, buffPos); + fir::StoreOp::create(builder, loc, plusOne, buffPos); } }, [&](const fir::ArrayBoxValue &v) { doAbstractArray(v); }, @@ -6402,8 +6416,8 @@ class ArrayExprLowering { auto seqTy = mlir::cast(resTy); mlir::Type eleTy = fir::unwrapSequenceType(seqTy); auto loop = - builder.create(loc, lo, up, step, /*unordered=*/false, - /*finalCount=*/false, mem); + fir::DoLoopOp::create(builder, loc, lo, up, step, /*unordered=*/false, + /*finalCount=*/false, mem); // create a new binding for x.name(), to ac-do-variable, to the iteration // value. symMap.pushImpliedDoBinding(toStringRef(x.name()), loop.getInductionVar()); @@ -6433,22 +6447,22 @@ class ArrayExprLowering { mlir::Value castLen = builder.createConvert(loc, builder.getI64Type(), fir::getLen(exv)); assert(charLen.has_value()); - builder.create(loc, castLen, *charLen); + fir::StoreOp::create(builder, loc, castLen, *charLen); } } stmtCtx.finalizeAndPop(); - builder.create(loc, mem); + fir::ResultOp::create(builder, loc, mem); builder.restoreInsertionPoint(insPt); mem = loop.getResult(0); symMap.popImpliedDoBinding(); llvm::SmallVector extents = { - builder.create(loc, buffPos).getResult()}; + fir::LoadOp::create(builder, loc, buffPos).getResult()}; // Convert to extended value. if (fir::isa_char(seqTy.getEleTy())) { assert(charLen.has_value()); - auto len = builder.create(loc, *charLen); + auto len = fir::LoadOp::create(builder, loc, *charLen); return {fir::CharArrayBoxValue{mem, len, extents}, /*needCopy=*/false}; } return {fir::ArrayBoxValue{mem, extents}, /*needCopy=*/false}; @@ -6471,7 +6485,7 @@ class ArrayExprLowering { mlir::Value buffSize = builder.createTemporary(loc, idxTy, ".buff.size"); mlir::Value zero = builder.createIntegerConstant(loc, idxTy, 0); mlir::Value buffPos = builder.createTemporary(loc, idxTy, ".buff.pos"); - builder.create(loc, zero, buffPos); + fir::StoreOp::create(builder, loc, zero, buffPos); // Allocate space for the array to be constructed. mlir::Value mem; if (fir::hasDynamicSize(resTy)) { @@ -6479,22 +6493,22 @@ class ArrayExprLowering { // The size of each element may depend on a general expression. Defer // creating the buffer until after the expression is evaluated. mem = builder.createNullConstant(loc, builder.getRefType(eleTy)); - builder.create(loc, zero, buffSize); + fir::StoreOp::create(builder, loc, zero, buffSize); } else { mlir::Value initBuffSz = builder.createIntegerConstant(loc, idxTy, clInitialBufferSize); - mem = builder.create( - loc, eleTy, /*typeparams=*/std::nullopt, initBuffSz); - builder.create(loc, initBuffSz, buffSize); + mem = fir::AllocMemOp::create( + builder, loc, eleTy, /*typeparams=*/mlir::ValueRange{}, initBuffSz); + fir::StoreOp::create(builder, loc, initBuffSz, buffSize); } } else { - mem = builder.create(loc, resTy); + mem = fir::AllocMemOp::create(builder, loc, resTy); int64_t buffSz = 1; for (auto extent : seqTy.getShape()) buffSz *= extent; mlir::Value initBuffSz = builder.createIntegerConstant(loc, idxTy, buffSz); - builder.create(loc, initBuffSz, buffSize); + fir::StoreOp::create(builder, loc, initBuffSz, buffSize); } // Compute size of element mlir::Type eleRefTy = builder.getRefType(eleTy); @@ -6516,12 +6530,12 @@ class ArrayExprLowering { charLen = builder.createTemporary(loc, builder.getI64Type()); mlir::Value castLen = builder.createConvert(loc, builder.getI64Type(), fir::getLen(exv)); - builder.create(loc, castLen, *charLen); + fir::StoreOp::create(builder, loc, castLen, *charLen); } } mem = builder.createConvert(loc, fir::HeapType::get(resTy), mem); llvm::SmallVector extents = { - builder.create(loc, buffPos)}; + fir::LoadOp::create(builder, loc, buffPos)}; // Cleanup the temporary. fir::FirOpBuilder *bldr = &converter.getFirOpBuilder(); @@ -6531,7 +6545,7 @@ class ArrayExprLowering { // Return the continuation. if (fir::isa_char(seqTy.getEleTy())) { if (charLen) { - auto len = builder.create(loc, *charLen); + auto len = fir::LoadOp::create(builder, loc, *charLen); return genarr(fir::CharArrayBoxValue{mem, len, extents}); } return genarr(fir::CharArrayBoxValue{mem, zero, extents}); @@ -6568,7 +6582,7 @@ class ArrayExprLowering { return [=](IterSpace iters) -> ExtValue { mlir::Value logical = fir::getBase(lambda(iters)); mlir::Value val = builder.createConvert(loc, i1Ty, logical); - return builder.create(loc, val, truth); + return mlir::arith::XOrIOp::create(builder, loc, val, truth); }; } template @@ -6582,7 +6596,7 @@ class ArrayExprLowering { mlir::Value right = fir::getBase(rf(iters)); mlir::Value lhs = builder.createConvert(loc, i1Ty, left); mlir::Value rhs = builder.createConvert(loc, i1Ty, right); - return builder.create(loc, lhs, rhs); + return OP::create(builder, loc, lhs, rhs); }; } template @@ -6596,7 +6610,7 @@ class ArrayExprLowering { mlir::Value right = fir::getBase(rf(iters)); mlir::Value lhs = builder.createConvert(loc, i1Ty, left); mlir::Value rhs = builder.createConvert(loc, i1Ty, right); - return builder.create(loc, pred, lhs, rhs); + return OP::create(builder, loc, pred, lhs, rhs); }; } template @@ -6636,9 +6650,9 @@ class ArrayExprLowering { Fortran::common::TypeCategory::Integer, *unsignedKind); mlir::Value lhsSL = builder.createConvert(loc, signlessType, lhs); mlir::Value rhsSL = builder.createConvert(loc, signlessType, rhs); - return builder.create(loc, pred, lhsSL, rhsSL); + return OP::create(builder, loc, pred, lhsSL, rhsSL); } - return builder.create(loc, pred, lhs, rhs); + return OP::create(builder, loc, pred, lhs, rhs); }; } template @@ -6805,9 +6819,8 @@ class ArrayExprLowering { : one; mlir::Value val = builder.createConvert( loc, idxTy, subscriptVal); - mlir::Value ivAdj = - builder.create( - loc, idxTy, val, lb); + mlir::Value ivAdj = mlir::arith::SubIOp::create( + builder, loc, idxTy, val, lb); componentsToAdd.push_back( builder.createConvert(loc, idxTy, ivAdj)); }, @@ -6829,8 +6842,9 @@ class ArrayExprLowering { converter.getRecordTypeFieldName(getLastSym(*x)); if (auto recTy = mlir::dyn_cast(ty)) { ty = recTy.getType(name); - auto fld = builder.create( - loc, fieldTy, name, recTy, fir::getTypeParams(arrayExv)); + auto fld = fir::FieldIndexOp::create( + builder, loc, fieldTy, name, recTy, + fir::getTypeParams(arrayExv)); addComponentList(ty, {fld}); if (index != revPath.size() - 1 || !isPointerAssignment()) { // Need an intermediate dereference if the boxed value @@ -6851,8 +6865,9 @@ class ArrayExprLowering { ty = fir::unwrapRefType(boxTy.getEleTy()); auto recTy = mlir::cast(ty); ty = recTy.getType(name); - auto fld = builder.create( - loc, fieldTy, name, recTy, fir::getTypeParams(arrayExv)); + auto fld = fir::FieldIndexOp::create( + builder, loc, fieldTy, name, recTy, + fir::getTypeParams(arrayExv)); extendComponent(components, ty, {fld}); } else { TODO(loc, "other component type"); @@ -6895,8 +6910,8 @@ class ArrayExprLowering { mlir::Value innerArg = esp->findArgumentOfLoad(load); if (isAdjustedArrayElementType(eleTy)) { mlir::Type eleRefTy = builder.getRefType(eleTy); - auto arrayOp = builder.create( - loc, eleRefTy, innerArg, iters.iterVec(), + auto arrayOp = fir::ArrayAccessOp::create( + builder, loc, eleRefTy, innerArg, iters.iterVec(), fir::factory::getTypeParams(loc, builder, load)); if (auto charTy = mlir::dyn_cast(eleTy)) { mlir::Value dstLen = fir::factory::genLenOfCharacter( @@ -6923,9 +6938,9 @@ class ArrayExprLowering { if (!eleBoxTy || !mlir::isa(eleBoxTy)) TODO(loc, "assignment in a FORALL involving a designator with a " "POINTER or ALLOCATABLE component part-ref"); - auto arrayOp = builder.create( - loc, builder.getRefType(eleBoxTy), innerArg, iters.iterVec(), - fir::factory::getTypeParams(loc, builder, load)); + auto arrayOp = fir::ArrayAccessOp::create( + builder, loc, builder.getRefType(eleBoxTy), innerArg, + iters.iterVec(), fir::factory::getTypeParams(loc, builder, load)); mlir::Value addr = components.getExtendCoorRef()(arrayOp); components.resetExtendCoorRef(); // When the lhs is a boxed value and the context is not a pointer @@ -6934,19 +6949,19 @@ class ArrayExprLowering { if (!isPointerAssignment()) { if (auto boxTy = mlir::dyn_cast(eleTy)) { eleTy = fir::boxMemRefType(boxTy); - addr = builder.create(loc, eleTy, addr); + addr = fir::BoxAddrOp::create(builder, loc, eleTy, addr); eleTy = fir::unwrapRefType(eleTy); } } auto ele = convertElementForUpdate(loc, eleTy, iters.getElement()); - builder.create(loc, ele, addr); - auto amend = builder.create( - loc, innerArg.getType(), innerArg, arrayOp); + fir::StoreOp::create(builder, loc, ele, addr); + auto amend = fir::ArrayAmendOp::create( + builder, loc, innerArg.getType(), innerArg, arrayOp); return arrayLoadExtValue(builder, loc, load, iters.iterVec(), amend); } auto ele = convertElementForUpdate(loc, eleTy, iters.getElement()); - auto update = builder.create( - loc, innerArg.getType(), innerArg, ele, iters.iterVec(), + auto update = fir::ArrayUpdateOp::create( + builder, loc, innerArg.getType(), innerArg, ele, iters.iterVec(), fir::factory::getTypeParams(loc, builder, load)); return arrayLoadExtValue(builder, loc, load, iters.iterVec(), update); }; @@ -6960,9 +6975,9 @@ class ArrayExprLowering { mlir::Value innerArg = explicitSpace->findArgumentOfLoad(load); mlir::Type refEleTy = fir::isa_ref_type(eleTy) ? eleTy : builder.getRefType(eleTy); - auto arrModify = builder.create( - loc, mlir::TypeRange{refEleTy, innerArg.getType()}, innerArg, - iters.iterVec(), load.getTypeparams()); + auto arrModify = fir::ArrayModifyOp::create( + builder, loc, mlir::TypeRange{refEleTy, innerArg.getType()}, + innerArg, iters.iterVec(), load.getTypeparams()); return arrayLoadExtValue(builder, loc, load, iters.iterVec(), arrModify.getResult(1)); }; @@ -6973,8 +6988,8 @@ class ArrayExprLowering { isAdjustedArrayElementType(eleTy)) { mlir::Type resTy = builder.getRefType(eleTy); // Use array element reference semantics. - auto access = builder.create( - loc, resTy, load, iters.iterVec(), + auto access = fir::ArrayAccessOp::create( + builder, loc, resTy, load, iters.iterVec(), fir::factory::getTypeParams(loc, builder, load)); mlir::Value newBase = access; if (fir::isa_char(eleTy)) { @@ -6996,8 +7011,8 @@ class ArrayExprLowering { if (!eleBoxTy || !mlir::isa(eleBoxTy)) TODO(loc, "assignment in a FORALL involving a designator with a " "POINTER or ALLOCATABLE component part-ref"); - auto access = builder.create( - loc, builder.getRefType(eleBoxTy), load, iters.iterVec(), + auto access = fir::ArrayAccessOp::create( + builder, loc, builder.getRefType(eleBoxTy), load, iters.iterVec(), fir::factory::getTypeParams(loc, builder, load)); mlir::Value addr = components.getExtendCoorRef()(access); components.resetExtendCoorRef(); @@ -7009,8 +7024,8 @@ class ArrayExprLowering { // Rhs is a regular expression that will need to be boxed before // assigning to the boxed variable. auto typeParams = fir::factory::getTypeParams(loc, builder, load); - auto access = builder.create( - loc, builder.getRefType(eleTy), load, iters.iterVec(), + auto access = fir::ArrayAccessOp::create( + builder, loc, builder.getRefType(eleTy), load, iters.iterVec(), typeParams); auto addr = components.getExtendCoorRef()(access); components.resetExtendCoorRef(); @@ -7024,14 +7039,14 @@ class ArrayExprLowering { TODO(loc, "need to adjust typeparameter(s) to reflect the final " "component"); mlir::Value embox = - builder.create(loc, boxTy, ptrAddr, - /*shape=*/mlir::Value{}, - /*slice=*/mlir::Value{}, typeParams); + fir::EmboxOp::create(builder, loc, boxTy, ptrAddr, + /*shape=*/mlir::Value{}, + /*slice=*/mlir::Value{}, typeParams); return arrayLoadExtValue(builder, loc, load, iters.iterVec(), embox); } } - auto fetch = builder.create( - loc, eleTy, load, iters.iterVec(), load.getTypeparams()); + auto fetch = fir::ArrayFetchOp::create( + builder, loc, eleTy, load, iters.iterVec(), load.getTypeparams()); return arrayLoadExtValue(builder, loc, load, iters.iterVec(), fetch); }; return [=](IterSpace iters) mutable { return lambda(pc(iters)); }; @@ -7540,24 +7555,25 @@ fir::ExtendedValue Fortran::lower::updateBoxForParentComponent( if (op) { if (auto embox = mlir::dyn_cast(op)) { - auto newBox = builder.create( - loc, fir::BoxType::get(actualTy), embox.getMemref(), embox.getShape(), - embox.getSlice(), embox.getTypeparams()); + auto newBox = fir::EmboxOp::create( + builder, loc, fir::BoxType::get(actualTy), embox.getMemref(), + embox.getShape(), embox.getSlice(), embox.getTypeparams()); return fir::substBase(box, newBox); } if (auto rebox = mlir::dyn_cast(op)) { - auto newBox = builder.create( - loc, fir::BoxType::get(actualTy), rebox.getBox(), rebox.getShape(), - rebox.getSlice()); + auto newBox = fir::ReboxOp::create( + builder, loc, fir::BoxType::get(actualTy), rebox.getBox(), + rebox.getShape(), rebox.getSlice()); return fir::substBase(box, newBox); } } mlir::Value empty; mlir::ValueRange emptyRange; - return builder.create(loc, fir::BoxType::get(actualTy), boxBase, - /*shape=*/empty, - /*slice=*/empty); + return fir::ReboxOp::create(builder, loc, fir::BoxType::get(actualTy), + boxBase, + /*shape=*/empty, + /*slice=*/empty); } fir::ExtendedValue Fortran::lower::createBoxValue( @@ -7648,9 +7664,9 @@ fir::ArrayLoadOp genArrayLoad(mlir::Location loc, mlir::Value addr = fir::getBase(exv); mlir::Value shapeOp = builder.createShape(loc, exv); mlir::Type arrTy = fir::dyn_cast_ptrOrBoxEleTy(addr.getType()); - return builder.create(loc, arrTy, addr, shapeOp, - /*slice=*/mlir::Value{}, - fir::getTypeParams(exv)); + return fir::ArrayLoadOp::create(builder, loc, arrTy, addr, shapeOp, + /*slice=*/mlir::Value{}, + fir::getTypeParams(exv)); } template <> fir::ArrayLoadOp @@ -7697,9 +7713,9 @@ void Fortran::lower::createArrayMergeStores( for (auto i : llvm::enumerate(esp.getOuterLoop().getResults())) if (std::optional ldOpt = esp.getLhsLoad(i.index())) { fir::ArrayLoadOp load = *ldOpt; - builder.create(loc, load, i.value(), - load.getMemref(), load.getSlice(), - load.getTypeparams()); + fir::ArrayMergeStoreOp::create(builder, loc, load, i.value(), + load.getMemref(), load.getSlice(), + load.getTypeparams()); } if (esp.loopCleanup) { (*esp.loopCleanup)(builder); @@ -7721,12 +7737,12 @@ mlir::Value Fortran::lower::addCrayPointerInst(mlir::Location loc, mlir::Value empty; mlir::ValueRange emptyRange; auto boxTy = fir::BoxType::get(ptrTy); - auto box = builder.create(loc, boxTy, ptrVal, empty, empty, - emptyRange); - mlir::Value addrof = - (mlir::isa(ptrTy)) - ? builder.create(loc, ptrTy, box) - : builder.create(loc, builder.getRefType(ptrTy), box); + auto box = fir::EmboxOp::create(builder, loc, boxTy, ptrVal, empty, empty, + emptyRange); + mlir::Value addrof = (mlir::isa(ptrTy)) + ? fir::BoxAddrOp::create(builder, loc, ptrTy, box) + : fir::BoxAddrOp::create( + builder, loc, builder.getRefType(ptrTy), box); auto refPtrTy = builder.getRefType(fir::PointerType::get(fir::dyn_cast_ptrEleTy(pteTy))); diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp index 9689f920840fb..46be111242bf7 100644 --- a/flang/lib/Lower/ConvertExprToHLFIR.cpp +++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp @@ -167,7 +167,7 @@ class HlfirDesignatorBuilder { extents.push_back(builder.createIntegerConstant(loc, idxTy, extent)); } if (!mayHaveNonDefaultLowerBounds(componentSym)) - return builder.create(loc, extents); + return fir::ShapeOp::create(builder, loc, extents); llvm::SmallVector lbounds; if (const auto *objDetails = @@ -312,8 +312,8 @@ class HlfirDesignatorBuilder { // hlfir.elemental_addr. if (auto elementalAddrOp = getVectorSubscriptElementAddrOp()) builder.setInsertionPointToEnd(&elementalAddrOp->getBody().front()); - auto designate = builder.create( - getLoc(), designatorType, partInfo.base.value().getBase(), + auto designate = hlfir::DesignateOp::create( + builder, getLoc(), designatorType, partInfo.base.value().getBase(), partInfo.componentName, partInfo.componentShape, partInfo.subscripts, partInfo.substring, partInfo.complexPart, partInfo.resultShape, partInfo.typeParams, attributes); @@ -344,7 +344,7 @@ class HlfirDesignatorBuilder { mlir::Type refPtrType = builder.getRefType( fir::PointerType::get(fir::dyn_cast_ptrEleTy(ptrAddr.getType()))); mlir::Value cast = builder.createConvert(loc, refPtrType, ptrAddr); - mlir::Value ptrVal = builder.create(loc, cast); + mlir::Value ptrVal = fir::LoadOp::create(builder, loc, cast); // Update the base_addr to the value of the Cray pointer. // This is a hacky way to do the update, and it may harm @@ -442,9 +442,9 @@ class HlfirDesignatorBuilder { } else { // Compute "len = max(ub-lb+1,0)" (Fortran 2018 9.4.1). mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1); - auto boundsDiff = builder.create( - loc, partInfo.substring[1], partInfo.substring[0]); - auto rawLen = builder.create(loc, boundsDiff, one); + auto boundsDiff = mlir::arith::SubIOp::create( + builder, loc, partInfo.substring[1], partInfo.substring[0]); + auto rawLen = mlir::arith::AddIOp::create(builder, loc, boundsDiff, one); partInfo.typeParams[0] = fir::factory::genMaxWithZero(builder, loc, rawLen); } @@ -803,10 +803,10 @@ class HlfirDesignatorBuilder { mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1); oneBasedIndex = builder.createConvert(loc, idxTy, oneBasedIndex); mlir::Value zeroBased = - builder.create(loc, oneBasedIndex, one); + mlir::arith::SubIOp::create(builder, loc, oneBasedIndex, one); mlir::Value offset = - builder.create(loc, zeroBased, step); - return builder.create(loc, lb, offset); + mlir::arith::MulIOp::create(builder, loc, zeroBased, step); + return mlir::arith::AddIOp::create(builder, loc, lb, offset); } /// Create an hlfir.element_addr operation to deal with vector subscripted @@ -836,8 +836,8 @@ class HlfirDesignatorBuilder { assert(partInfo.base.has_value() && "vector subscripted part must have a base"); mlir::Value mold = *partInfo.base; - auto elementalAddrOp = builder.create( - loc, shape, mold, mlir::ValueRange{}, + auto elementalAddrOp = hlfir::ElementalAddrOp::create( + builder, loc, shape, mold, mlir::ValueRange{}, /*isUnordered=*/true); setVectorSubscriptElementAddrOp(elementalAddrOp); builder.setInsertionPointToEnd(&elementalAddrOp.getBody().front()); @@ -881,7 +881,7 @@ class HlfirDesignatorBuilder { builder.setInsertionPointToEnd(&elementalAddrOp.getBody().front()); if (!elementAddr.isPolymorphic()) elementalAddrOp.getMoldMutable().clear(); - builder.create(loc, elementAddr); + hlfir::YieldOp::create(builder, loc, elementAddr); builder.setInsertionPointAfter(elementalAddrOp); } @@ -1001,7 +1001,7 @@ HlfirDesignatorBuilder::convertVectorSubscriptedExprToElementalAddr( elementalAddrOp.getMoldMutable().clear(); // Create the hlfir.yield terminator inside the hlfir.elemental_body. builder.setInsertionPointToEnd(&elementalAddrOp.getBody().front()); - builder.create(loc, elementAddrEntity); + hlfir::YieldOp::create(builder, loc, elementAddrEntity); builder.setInsertionPointAfter(elementalAddrOp); // Reset the HlfirDesignatorBuilder state, in case it is used on a new // designator. @@ -1034,7 +1034,7 @@ struct BinaryOp {}; rhs)}; \ } else { \ return hlfir::EntityWithAttributes{ \ - builder.create(loc, lhs, rhs)}; \ + GenBinFirOp::create(builder, loc, lhs, rhs)}; \ } \ } \ }; @@ -1075,7 +1075,7 @@ struct BinaryOp(loc, lhs, rhs)}; + mlir::complex::DivOp::create(builder, loc, lhs, rhs)}; } } }; @@ -1219,8 +1219,8 @@ struct BinaryOp( - loc, translateSignedRelational(op.opr), lhs, rhs); + auto cmp = mlir::arith::CmpIOp::create( + builder, loc, translateSignedRelational(op.opr), lhs, rhs); return hlfir::EntityWithAttributes{cmp}; } }; @@ -1241,8 +1241,8 @@ struct BinaryOp( - loc, translateUnsignedRelational(op.opr), lhsSL, rhsSL); + auto cmp = mlir::arith::CmpIOp::create( + builder, loc, translateUnsignedRelational(op.opr), lhsSL, rhsSL); return hlfir::EntityWithAttributes{cmp}; } }; @@ -1256,8 +1256,8 @@ struct BinaryOp( - loc, translateFloatRelational(op.opr), lhs, rhs); + auto cmp = mlir::arith::CmpFOp::create( + builder, loc, translateFloatRelational(op.opr), lhs, rhs); return hlfir::EntityWithAttributes{cmp}; } }; @@ -1271,8 +1271,8 @@ struct BinaryOp( - loc, translateFloatRelational(op.opr), lhs, rhs); + auto cmp = fir::CmpcOp::create(builder, loc, + translateFloatRelational(op.opr), lhs, rhs); return hlfir::EntityWithAttributes{cmp}; } }; @@ -1313,16 +1313,16 @@ struct BinaryOp> { switch (op.logicalOperator) { case Fortran::evaluate::LogicalOperator::And: return hlfir::EntityWithAttributes{ - builder.create(loc, i1Lhs, i1Rhs)}; + mlir::arith::AndIOp::create(builder, loc, i1Lhs, i1Rhs)}; case Fortran::evaluate::LogicalOperator::Or: return hlfir::EntityWithAttributes{ - builder.create(loc, i1Lhs, i1Rhs)}; + mlir::arith::OrIOp::create(builder, loc, i1Lhs, i1Rhs)}; case Fortran::evaluate::LogicalOperator::Eqv: - return hlfir::EntityWithAttributes{builder.create( - loc, mlir::arith::CmpIPredicate::eq, i1Lhs, i1Rhs)}; + return hlfir::EntityWithAttributes{mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, i1Lhs, i1Rhs)}; case Fortran::evaluate::LogicalOperator::Neqv: - return hlfir::EntityWithAttributes{builder.create( - loc, mlir::arith::CmpIPredicate::ne, i1Lhs, i1Rhs)}; + return hlfir::EntityWithAttributes{mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::ne, i1Lhs, i1Rhs)}; case Fortran::evaluate::LogicalOperator::Not: // lib/evaluate expression for .NOT. is Fortran::evaluate::Not. llvm_unreachable(".NOT. is not a binary operator"); @@ -1354,7 +1354,7 @@ struct BinaryOp> { // Fortran 2018 7.4.4.2 point 5. mlir::Value safeLength = fir::factory::genMaxWithZero(builder, loc, length); return hlfir::EntityWithAttributes{ - builder.create(loc, string, safeLength)}; + hlfir::SetLengthOp::create(builder, loc, string, safeLength)}; } static void genResultTypeParams(mlir::Location, fir::FirOpBuilder &, hlfir::Entity, @@ -1372,7 +1372,7 @@ struct BinaryOp> { hlfir::Entity lhs, hlfir::Entity rhs) { assert(len && "genResultTypeParams must have been called"); auto concat = - builder.create(loc, mlir::ValueRange{lhs, rhs}, len); + hlfir::ConcatOp::create(builder, loc, mlir::ValueRange{lhs, rhs}, len); return hlfir::EntityWithAttributes{concat.getResult()}; } void @@ -1386,7 +1386,7 @@ struct BinaryOp> { mlir::Type idxType = builder.getIndexType(); mlir::Value lhsLen = builder.createConvert(loc, idxType, lengths[0]); mlir::Value rhsLen = builder.createConvert(loc, idxType, lengths[1]); - len = builder.create(loc, lhsLen, rhsLen); + len = mlir::arith::AddIOp::create(builder, loc, lhsLen, rhsLen); resultTypeParams.push_back(len); } @@ -1410,7 +1410,7 @@ struct UnaryOp> { mlir::Value one = builder.createBool(loc, true); mlir::Value val = builder.createConvert(loc, builder.getI1Type(), lhs); return hlfir::EntityWithAttributes{ - builder.create(loc, val, one)}; + mlir::arith::XOrIOp::create(builder, loc, val, one)}; } }; @@ -1428,7 +1428,7 @@ struct UnaryOp(loc, zero, lhs)}; + mlir::arith::SubIOp::create(builder, loc, zero, lhs)}; } }; @@ -1448,7 +1448,7 @@ struct UnaryOp(loc, zero, signless); + mlir::arith::SubIOp::create(builder, loc, zero, signless); return hlfir::EntityWithAttributes( builder.createConvert(loc, lhs.getType(), negated)); } @@ -1463,7 +1463,7 @@ struct UnaryOp(loc, lhs)}; + mlir::arith::NegFOp::create(builder, loc, lhs)}; } }; @@ -1475,7 +1475,7 @@ struct UnaryOp(loc, lhs)}; + return hlfir::EntityWithAttributes{fir::NegcOp::create(builder, loc, lhs)}; } }; @@ -1499,9 +1499,9 @@ struct UnaryOp> { const Op &op, hlfir::Entity lhs) { if (lhs.isVariable()) return hlfir::EntityWithAttributes{ - builder.create(loc, lhs)}; + hlfir::AsExprOp::create(builder, loc, lhs)}; return hlfir::EntityWithAttributes{ - builder.create(loc, lhs.getType(), lhs)}; + hlfir::NoReassocOp::create(builder, loc, lhs.getType(), lhs)}; } static void @@ -1822,8 +1822,8 @@ class HlfirBuilder { // Allocate scalar temporary that will be initialized // with the values specified by the constructor. mlir::Value storagePtr = builder.createTemporary(loc, recTy); - auto varOp = hlfir::EntityWithAttributes{builder.create( - loc, storagePtr, "ctor.temp", /*shape=*/nullptr, + auto varOp = hlfir::EntityWithAttributes{hlfir::DeclareOp::create( + builder, loc, storagePtr, "ctor.temp", /*shape=*/nullptr, /*typeparams=*/mlir::ValueRange{}, /*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{})}; @@ -1855,8 +1855,8 @@ class HlfirBuilder { auto parentCompType = baseRecTy.getType(parentName); assert(parentCompType && "failed to retrieve parent component type"); mlir::Type designatorType = builder.getRefType(parentCompType); - mlir::Value newParent = builder.create( - loc, designatorType, currentParent, parentName, + mlir::Value newParent = hlfir::DesignateOp::create( + builder, loc, designatorType, currentParent, parentName, /*compShape=*/mlir::Value{}, hlfir::DesignateOp::Subscripts{}, /*substring=*/mlir::ValueRange{}, /*complexPart=*/std::nullopt, @@ -1912,8 +1912,8 @@ class HlfirBuilder { extraAttributeFlags); // Get the component designator. - auto lhs = builder.create( - loc, designatorType, baseOp, name, compShape, + auto lhs = hlfir::DesignateOp::create( + builder, loc, designatorType, baseOp, name, compShape, hlfir::DesignateOp::Subscripts{}, /*substring=*/mlir::ValueRange{}, /*complexPart=*/std::nullopt, @@ -1945,7 +1945,7 @@ class HlfirBuilder { fir::emitFatalError(loc, "pointer component designator could not be " "lowered to mutable box"); Fortran::lower::associateMutableBox(converter, loc, *toBox, expr, - /*lbounds=*/std::nullopt, stmtCtx); + /*lbounds=*/{}, stmtCtx); continue; } @@ -1997,10 +1997,10 @@ class HlfirBuilder { auto rhsCastAndCleanup = hlfir::genTypeAndKindConvert(loc, builder, rhs, lhs.getType(), /*preserveLowerBounds=*/allowRealloc); - builder.create(loc, rhsCastAndCleanup.first, lhs, - allowRealloc, - allowRealloc ? keepLhsLength : false, - /*temporary_lhs=*/true); + hlfir::AssignOp::create(builder, loc, rhsCastAndCleanup.first, lhs, + allowRealloc, + allowRealloc ? keepLhsLength : false, + /*temporary_lhs=*/true); if (rhsCastAndCleanup.second) (*rhsCastAndCleanup.second)(); }; diff --git a/flang/lib/Lower/ConvertProcedureDesignator.cpp b/flang/lib/Lower/ConvertProcedureDesignator.cpp index b528544ec245c..d4c535d71cb5f 100644 --- a/flang/lib/Lower/ConvertProcedureDesignator.cpp +++ b/flang/lib/Lower/ConvertProcedureDesignator.cpp @@ -49,7 +49,7 @@ fir::ExtendedValue Fortran::lower::convertProcedureDesignator( fir::getUnrestrictedIntrinsicSymbolRefAttr(builder, loc, genericName, signature); mlir::Value funcPtr = - builder.create(loc, signature, symbolRefAttr); + fir::AddrOfOp::create(builder, loc, signature, symbolRefAttr); return funcPtr; } const Fortran::semantics::Symbol *symbol = proc.GetSymbol(); @@ -69,7 +69,7 @@ fir::ExtendedValue Fortran::lower::convertProcedureDesignator( Fortran::lower::getOrDeclareFunction(proc, converter); mlir::SymbolRefAttr nameAttr = builder.getSymbolRefAttr(func.getSymName()); funcPtr = - builder.create(loc, func.getFunctionType(), nameAttr); + fir::AddrOfOp::create(builder, loc, func.getFunctionType(), nameAttr); } if (Fortran::lower::mustPassLengthWithDummyProcedure(proc, converter)) { // The result length, if available here, must be propagated along the @@ -114,7 +114,7 @@ static hlfir::EntityWithAttributes designateProcedurePointerComponent( /// Passed argument may be a descriptor. This is a scalar reference, so the /// base address can be directly addressed. if (mlir::isa(base.getType())) - base = builder.create(loc, base); + base = fir::BoxAddrOp::create(builder, loc, base); std::string fieldName = converter.getRecordTypeFieldName(procComponentSym); auto recordType = mlir::cast(hlfir::getFortranElementType(base.getType())); @@ -124,8 +124,8 @@ static hlfir::EntityWithAttributes designateProcedurePointerComponent( if (!fieldType) TODO(loc, "passing type bound procedure (extension)"); mlir::Type designatorType = fir::ReferenceType::get(fieldType); - mlir::Value compRef = builder.create( - loc, designatorType, base, fieldName, + mlir::Value compRef = hlfir::DesignateOp::create( + builder, loc, designatorType, base, fieldName, /*compShape=*/mlir::Value{}, hlfir::DesignateOp::Subscripts{}, /*substring=*/mlir::ValueRange{}, /*complexPart=*/std::nullopt, @@ -174,10 +174,10 @@ hlfir::EntityWithAttributes Fortran::lower::convertProcedureDesignatorToHLFIR( mlir::Type boxTy = Fortran::lower::getUntypedBoxProcType(&converter.getMLIRContext()); if (auto host = Fortran::lower::argumentHostAssocs(converter, funcAddr)) - funcAddr = builder.create( - loc, boxTy, llvm::ArrayRef{funcAddr, host}); + funcAddr = fir::EmboxProcOp::create( + builder, loc, boxTy, llvm::ArrayRef{funcAddr, host}); else - funcAddr = builder.create(loc, boxTy, funcAddr); + funcAddr = fir::EmboxProcOp::create(builder, loc, boxTy, funcAddr); } mlir::Value res = procExv.match( diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp index 2bfa9618aa4b9..647bd0d079985 100644 --- a/flang/lib/Lower/ConvertVariable.cpp +++ b/flang/lib/Lower/ConvertVariable.cpp @@ -236,9 +236,8 @@ mlir::Value Fortran::lower::genInitialDataTarget( fir::FirOpBuilder &builder = converter.getFirOpBuilder(); if (Fortran::evaluate::UnwrapExpr( initialTarget)) - return fir::factory::createUnallocatedBox( - builder, loc, boxType, - /*nonDeferredParams=*/std::nullopt); + return fir::factory::createUnallocatedBox(builder, loc, boxType, + /*nonDeferredParams=*/{}); // Pointer initial data target, and NULL(mold). for (const auto &sym : Fortran::evaluate::CollectSymbols(initialTarget)) { // Derived type component symbols should not be instantiated as objects @@ -313,8 +312,8 @@ mlir::Value Fortran::lower::genInitialDataTarget( // initial value of the descriptor). // Create a fir.rebox to set the attribute correctly, and use targetShift // to preserve the target lower bounds if any. - return builder.create(loc, boxType, targetBox, targetShift, - /*slice=*/mlir::Value{}); + return fir::ReboxOp::create(builder, loc, boxType, targetBox, targetShift, + /*slice=*/mlir::Value{}); } /// Generate default initial value for a derived type object \p sym with mlir @@ -354,8 +353,8 @@ static mlir::Value genComponentDefaultInit( // From a standard point of view, pointer without initialization do not // need to be disassociated, but for sanity and simplicity, do it in // global constructor since this has no runtime cost. - componentValue = fir::factory::createUnallocatedBox( - builder, loc, componentTy, std::nullopt); + componentValue = + fir::factory::createUnallocatedBox(builder, loc, componentTy, {}); } else if (Fortran::lower::hasDefaultInitialization(component)) { // Component type has default initialization. componentValue = genDefaultInitializerValue(converter, loc, component, @@ -363,7 +362,7 @@ static mlir::Value genComponentDefaultInit( } else { // Component has no initial value. Set its bits to zero by extension // to match what is expected because other compilers are doing it. - componentValue = builder.create(loc, componentTy); + componentValue = fir::ZeroOp::create(builder, loc, componentTy); } } else if (const auto *proc{ component @@ -378,17 +377,17 @@ static mlir::Value genComponentDefaultInit( componentValue = fir::factory::createNullBoxProc(builder, loc, componentTy); } else - componentValue = builder.create(loc, componentTy); + componentValue = fir::ZeroOp::create(builder, loc, componentTy); } assert(componentValue && "must have been computed"); componentValue = builder.createConvert(loc, componentTy, componentValue); auto fieldTy = fir::FieldType::get(recTy.getContext()); // FIXME: type parameters must come from the derived-type-spec - auto field = builder.create( - loc, fieldTy, name, recTy, - /*typeParams=*/mlir::ValueRange{} /*TODO*/); - return builder.create( - loc, recTy, insertInto, componentValue, + auto field = + fir::FieldIndexOp::create(builder, loc, fieldTy, name, recTy, + /*typeParams=*/mlir::ValueRange{} /*TODO*/); + return fir::InsertValueOp::create( + builder, loc, recTy, insertInto, componentValue, builder.getArrayAttr(field.getAttributes())); } @@ -406,7 +405,7 @@ static mlir::Value genDefaultInitializerValue( // Build a scalar default value of the symbol type, looping through the // components to build each component initial value. auto recTy = mlir::cast(scalarType); - mlir::Value initialValue = builder.create(loc, scalarType); + mlir::Value initialValue = fir::UndefOp::create(builder, loc, scalarType); const Fortran::semantics::DeclTypeSpec *declTy = sym.GetType(); assert(declTy && "var with default initialization must have a type"); @@ -445,7 +444,7 @@ static mlir::Value genDefaultInitializerValue( if (sequenceType) { // For arrays, duplicate the scalar value to all elements with an // fir.insert_range covering the whole array. - auto arrayInitialValue = builder.create(loc, sequenceType); + auto arrayInitialValue = fir::UndefOp::create(builder, loc, sequenceType); llvm::SmallVector rangeBounds; for (int64_t extent : sequenceType.getShape()) { if (extent == fir::SequenceType::getUnknownExtent()) @@ -454,8 +453,8 @@ static mlir::Value genDefaultInitializerValue( rangeBounds.push_back(0); rangeBounds.push_back(extent - 1); } - return builder.create( - loc, sequenceType, arrayInitialValue, initialValue, + return fir::InsertOnRangeOp::create( + builder, loc, sequenceType, arrayInitialValue, initialValue, builder.getIndexVectorAttr(rangeBounds)); } return initialValue; @@ -547,16 +546,16 @@ fir::GlobalOp Fortran::lower::defineGlobal( createGlobalInitialization(builder, global, [&](fir::FirOpBuilder &b) { mlir::Value box = Fortran::lower::genInitialDataTarget(converter, loc, symTy, expr); - b.create(loc, box); + fir::HasValueOp::create(b, loc, box); }); } else { // Create unallocated/disassociated descriptor if no explicit init createGlobalInitialization(builder, global, [&](fir::FirOpBuilder &b) { mlir::Value box = fir::factory::createUnallocatedBox( b, loc, symTy, - /*nonDeferredParams=*/std::nullopt, + /*nonDeferredParams=*/{}, /*typeSourceBox=*/{}, getAllocatorIdxFromDataAttr(dataAttr)); - b.create(loc, box); + fir::HasValueOp::create(b, loc, box); }); } } else if (const auto *details = @@ -570,7 +569,7 @@ fir::GlobalOp Fortran::lower::defineGlobal( converter, loc, details->init().value(), stmtCtx); mlir::Value castTo = builder.createConvert(loc, symTy, fir::getBase(initVal)); - builder.create(loc, castTo); + fir::HasValueOp::create(builder, loc, castTo); }); } else if (Fortran::lower::hasDefaultInitialization(sym)) { createGlobalInitialization( @@ -580,7 +579,7 @@ fir::GlobalOp Fortran::lower::defineGlobal( mlir::Value initVal = genDefaultInitializerValue(converter, loc, sym, symTy, stmtCtx); mlir::Value castTo = builder.createConvert(loc, symTy, initVal); - builder.create(loc, castTo); + fir::HasValueOp::create(builder, loc, castTo); }); } } else if (Fortran::semantics::IsProcedurePointer(sym)) { @@ -595,19 +594,19 @@ fir::GlobalOp Fortran::lower::defineGlobal( auto box{Fortran::lower::convertProcedureDesignatorInitialTarget( converter, loc, *sym)}; auto castTo{builder.createConvert(loc, symTy, box)}; - b.create(loc, castTo); + fir::HasValueOp::create(b, loc, castTo); }); else { // Has NULL() target. createGlobalInitialization(builder, global, [&](fir::FirOpBuilder &b) { auto box{fir::factory::createNullBoxProc(b, loc, symTy)}; - b.create(loc, box); + fir::HasValueOp::create(b, loc, box); }); } } else { // No initialization. createGlobalInitialization(builder, global, [&](fir::FirOpBuilder &b) { auto box{fir::factory::createNullBoxProc(b, loc, symTy)}; - b.create(loc, box); + fir::HasValueOp::create(b, loc, box); }); } } else if (sym.has()) { @@ -633,10 +632,10 @@ fir::GlobalOp Fortran::lower::defineGlobal( builder, global, [&](fir::FirOpBuilder &builder) { mlir::Value initValue; if (converter.getLoweringOptions().getInitGlobalZero()) - initValue = builder.create(loc, symTy); + initValue = fir::ZeroOp::create(builder, loc, symTy); else - initValue = builder.create(loc, symTy); - builder.create(loc, initValue); + initValue = fir::UndefOp::create(builder, loc, symTy); + fir::HasValueOp::create(builder, loc, initValue); }); } // Set public visibility to prevent global definition to be optimized out @@ -691,8 +690,8 @@ static void instantiateGlobal(Fortran::lower::AbstractConverter &converter, sym); global = defineGlobal(converter, var, globalName, linkage, dataAttr); } - auto addrOf = builder.create(loc, global.resultType(), - global.getSymbol()); + auto addrOf = fir::AddrOfOp::create(builder, loc, global.resultType(), + global.getSymbol()); // The type of the global cannot be trusted to be the same as the one // of the variable as some existing programs map common blocks to // BIND(C) module variables (e.g. mpi_argv_null in MPI and MPI_F08). @@ -753,7 +752,7 @@ static mlir::Value createNewLocal(Fortran::lower::AbstractConverter &converter, // would be a waste of space, and incorrect if the pointee is a non dummy // assumed-size (possible with cray pointee). if (ultimateSymbol.test(Fortran::semantics::Symbol::Flag::CrayPointee)) - return builder.create(loc, fir::ReferenceType::get(ty)); + return fir::ZeroOp::create(builder, loc, fir::ReferenceType::get(ty)); if (needCUDAAlloc(ultimateSymbol)) { cuf::DataAttributeAttr dataAttr = @@ -768,12 +767,12 @@ static mlir::Value createNewLocal(Fortran::lower::AbstractConverter &converter, for (mlir::Value sh : elidedShape) indices.push_back(builder.createConvert(loc, idxTy, sh)); if (dataAttr.getValue() == cuf::DataAttribute::Shared) - return builder.create(loc, ty, nm, symNm, lenParams, - indices); + return cuf::SharedMemoryOp::create(builder, loc, ty, nm, symNm, lenParams, + indices); if (!cuf::isCUDADeviceContext(builder.getRegion())) - return builder.create(loc, ty, nm, symNm, dataAttr, - lenParams, indices); + return cuf::AllocOp::create(builder, loc, ty, nm, symNm, dataAttr, + lenParams, indices); } // Let the builder do all the heavy lifting. @@ -783,7 +782,7 @@ static mlir::Value createNewLocal(Fortran::lower::AbstractConverter &converter, // Local procedure pointer. auto res{builder.allocateLocal(loc, ty, nm, symNm, shape, lenParams, isTarg)}; auto box{fir::factory::createNullBoxProc(builder, loc, ty)}; - builder.create(loc, box, res); + fir::StoreOp::create(builder, loc, box, res); return res; } @@ -802,13 +801,24 @@ initializeDeviceComponentAllocator(Fortran::lower::AbstractConverter &converter, const Fortran::semantics::DerivedTypeSpec *derived{type ? type->AsDerived() : nullptr}; if (derived) { + if (!FindCUDADeviceAllocatableUltimateComponent(*derived)) + return; // No device components. + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); mlir::Location loc = converter.getCurrentLocation(); fir::ExtendedValue exv = converter.getSymbolExtendedValue(symbol.GetUltimate(), &symMap); - auto recTy = mlir::dyn_cast( - fir::unwrapRefType(fir::getBase(exv).getType())); + mlir::Type baseTy = fir::unwrapRefType(fir::getBase(exv).getType()); + if (auto boxTy = mlir::dyn_cast(baseTy)) + baseTy = boxTy.getEleTy(); + baseTy = fir::unwrapRefType(baseTy); + + if (mlir::isa(baseTy)) + TODO(loc, "array of derived-type with device component"); + + auto recTy = + mlir::dyn_cast(fir::unwrapSequenceType(baseTy)); assert(recTy && "expected fir::RecordType"); llvm::SmallVector coordinates; @@ -817,15 +827,15 @@ initializeDeviceComponentAllocator(Fortran::lower::AbstractConverter &converter, if (Fortran::semantics::IsDeviceAllocatable(sym)) { unsigned fieldIdx = recTy.getFieldIndex(sym.name().ToString()); mlir::Type fieldTy; - std::vector coordinates; + llvm::SmallVector coordinates; if (fieldIdx != std::numeric_limits::max()) { // Field found in the base record type. auto fieldName = recTy.getTypeList()[fieldIdx].first; fieldTy = recTy.getTypeList()[fieldIdx].second; - mlir::Value fieldIndex = builder.create( - loc, fir::FieldType::get(fieldTy.getContext()), fieldName, - recTy, + mlir::Value fieldIndex = fir::FieldIndexOp::create( + builder, loc, fir::FieldType::get(fieldTy.getContext()), + fieldName, recTy, /*typeParams=*/mlir::ValueRange{}); coordinates.push_back(fieldIndex); } else { @@ -836,19 +846,18 @@ initializeDeviceComponentAllocator(Fortran::lower::AbstractConverter &converter, mlir::dyn_cast(component.second)) { fieldIdx = childRecTy.getFieldIndex(sym.name().ToString()); if (fieldIdx != std::numeric_limits::max()) { - mlir::Value parentFieldIndex = - builder.create( - loc, fir::FieldType::get(childRecTy.getContext()), - component.first, recTy, - /*typeParams=*/mlir::ValueRange{}); + mlir::Value parentFieldIndex = fir::FieldIndexOp::create( + builder, loc, + fir::FieldType::get(childRecTy.getContext()), + component.first, recTy, + /*typeParams=*/mlir::ValueRange{}); coordinates.push_back(parentFieldIndex); auto fieldName = childRecTy.getTypeList()[fieldIdx].first; fieldTy = childRecTy.getTypeList()[fieldIdx].second; - mlir::Value childFieldIndex = - builder.create( - loc, fir::FieldType::get(fieldTy.getContext()), - fieldName, childRecTy, - /*typeParams=*/mlir::ValueRange{}); + mlir::Value childFieldIndex = fir::FieldIndexOp::create( + builder, loc, fir::FieldType::get(fieldTy.getContext()), + fieldName, childRecTy, + /*typeParams=*/mlir::ValueRange{}); coordinates.push_back(childFieldIndex); break; } @@ -860,12 +869,28 @@ initializeDeviceComponentAllocator(Fortran::lower::AbstractConverter &converter, TODO(loc, "device resident component in complex derived-type " "hierarchy"); - mlir::Value comp = builder.create( - loc, builder.getRefType(fieldTy), fir::getBase(exv), coordinates); + mlir::Value base = fir::getBase(exv); + mlir::Value comp; + if (mlir::isa(fir::unwrapRefType(base.getType()))) { + mlir::Value box = fir::LoadOp::create(builder, loc, base); + mlir::Value addr = fir::BoxAddrOp::create(builder, loc, box); + llvm::SmallVector lenParams; + assert(coordinates.size() == 1 && "expect one coordinate"); + auto field = mlir::dyn_cast( + coordinates[0].getDefiningOp()); + comp = hlfir::DesignateOp::create( + builder, loc, builder.getRefType(fieldTy), addr, + /*component=*/field.getFieldName(), + /*componentShape=*/mlir::Value{}, + hlfir::DesignateOp::Subscripts{}); + } else { + comp = fir::CoordinateOp::create( + builder, loc, builder.getRefType(fieldTy), base, coordinates); + } cuf::DataAttributeAttr dataAttr = Fortran::lower::translateSymbolCUFDataAttribute( builder.getContext(), sym); - builder.create(loc, comp, dataAttr); + cuf::SetAllocatorIndexOp::create(builder, loc, comp, dataAttr); } } } @@ -907,8 +932,8 @@ void Fortran::lower::defaultInitializeAtRuntime( // 15.5.2.12 point 3, absent optional dummies are not initialized. // Creating descriptor/passing null descriptor to the runtime would // create runtime crashes. - auto isPresent = builder.create(loc, builder.getI1Type(), - fir::getBase(exv)); + auto isPresent = fir::IsPresentOp::create(builder, loc, builder.getI1Type(), + fir::getBase(exv)); builder.genIfThen(loc, isPresent) .genThen([&]() { auto box = builder.createBox(loc, exv); @@ -950,7 +975,7 @@ void Fortran::lower::defaultInitializeAtRuntime( converter, loc, details->init().value(), stmtCtx); mlir::Value castTo = builder.createConvert(loc, symTy, fir::getBase(initVal)); - builder.create(loc, castTo); + fir::HasValueOp::create(builder, loc, castTo); }); } else if (!global) { global = builder.createGlobal(loc, symTy, globalName, linkage, @@ -965,13 +990,13 @@ void Fortran::lower::defaultInitializeAtRuntime( mlir::Value initVal = genDefaultInitializerValue( converter, loc, sym, symTy, stmtCtx); mlir::Value castTo = builder.createConvert(loc, symTy, initVal); - builder.create(loc, castTo); + fir::HasValueOp::create(builder, loc, castTo); }); } - auto addrOf = builder.create(loc, global.resultType(), - global.getSymbol()); - builder.create(loc, addrOf, fir::getBase(exv), - /*noOverlap=*/true); + auto addrOf = fir::AddrOfOp::create(builder, loc, global.resultType(), + global.getSymbol()); + fir::CopyOp::create(builder, loc, addrOf, fir::getBase(exv), + /*noOverlap=*/true); } else { mlir::Value box = builder.createBox(loc, exv); fir::runtime::genDerivedTypeInitialize(builder, loc, box); @@ -1071,8 +1096,8 @@ static void finalizeAtRuntime(Fortran::lower::AbstractConverter &converter, fir::ExtendedValue exv = converter.getSymbolExtendedValue(sym, &symMap); if (Fortran::semantics::IsOptional(sym)) { // Only finalize if present. - auto isPresent = builder.create(loc, builder.getI1Type(), - fir::getBase(exv)); + auto isPresent = fir::IsPresentOp::create(builder, loc, builder.getI1Type(), + fir::getBase(exv)); builder.genIfThen(loc, isPresent) .genThen([&]() { auto box = builder.createBox(loc, exv); @@ -1118,8 +1143,8 @@ static void deallocateIntentOut(Fortran::lower::AbstractConverter &converter, fir::FirOpBuilder &builder = converter.getFirOpBuilder(); if (Fortran::semantics::IsOptional(sym)) { - auto isPresent = builder.create( - loc, builder.getI1Type(), fir::getBase(extVal)); + auto isPresent = fir::IsPresentOp::create( + builder, loc, builder.getI1Type(), fir::getBase(extVal)); builder.genIfThen(loc, isPresent) .genThen([&]() { Fortran::lower::genDeallocateIfAllocated(converter, *mutBox, loc); @@ -1332,7 +1357,7 @@ static fir::GlobalOp defineGlobalAggregateStore( Fortran::lower::StatementContext stmtCtx; mlir::Value initVal = fir::getBase(genInitializerExprValue( converter, loc, objectDetails->init().value(), stmtCtx)); - builder.create(loc, initVal); + fir::HasValueOp::create(builder, loc, initVal); }); return global; } @@ -1341,8 +1366,8 @@ static fir::GlobalOp defineGlobalAggregateStore( // of the linkage. createGlobalInitialization(builder, global, [&](fir::FirOpBuilder &builder) { Fortran::lower::StatementContext stmtCtx; - mlir::Value initVal = builder.create(loc, aggTy); - builder.create(loc, initVal); + mlir::Value initVal = fir::ZeroOp::create(builder, loc, aggTy); + fir::HasValueOp::create(builder, loc, initVal); }); return global; } @@ -1392,8 +1417,8 @@ instantiateAggregateStore(Fortran::lower::AbstractConverter &converter, global = defineGlobalAggregateStore(converter, aggregate, aggName, linkage); } - auto addr = builder.create(loc, global.resultType(), - global.getSymbol()); + auto addr = fir::AddrOfOp::create(builder, loc, global.resultType(), + global.getSymbol()); auto size = std::get<1>(var.getInterval()); fir::SequenceType::Shape shape(1, size); auto seqTy = fir::SequenceType::get(shape, i8Ty); @@ -1440,8 +1465,8 @@ static void instantiateAlias(Fortran::lower::AbstractConverter &converter, std::size_t off = sym.GetUltimate().offset() - var.getAliasOffset(); mlir::Value storeAddr = getAggregateStore(storeMap, var); mlir::Value offset = builder.createIntegerConstant(loc, idxTy, off); - mlir::Value bytePtr = builder.create( - loc, i8Ptr, storeAddr, mlir::ValueRange{offset}); + mlir::Value bytePtr = fir::CoordinateOp::create( + builder, loc, i8Ptr, storeAddr, mlir::ValueRange{offset}); mlir::Value typedPtr = castAliasToPointer(builder, loc, symType, bytePtr); Fortran::lower::StatementContext stmtCtx; mapSymbolAttributes(converter, var, symMap, stmtCtx, typedPtr); @@ -1630,7 +1655,7 @@ static void finalizeCommonBlockDefinition( mlir::TupleType commonTy = mlir::cast(global.getType()); auto initFunc = [&](fir::FirOpBuilder &builder) { mlir::IndexType idxTy = builder.getIndexType(); - mlir::Value cb = builder.create(loc, commonTy); + mlir::Value cb = fir::ZeroOp::create(builder, loc, commonTy); unsigned tupIdx = 0; std::size_t offset = 0; LLVM_DEBUG(llvm::dbgs() << "block {\n"); @@ -1654,15 +1679,15 @@ static void finalizeCommonBlockDefinition( mlir::IntegerAttr offVal = builder.getIntegerAttr(idxTy, tupIdx); mlir::Value castVal = builder.createConvert( loc, commonTy.getType(tupIdx), fir::getBase(initVal)); - cb = builder.create(loc, commonTy, cb, castVal, - builder.getArrayAttr(offVal)); + cb = fir::InsertValueOp::create(builder, loc, commonTy, cb, castVal, + builder.getArrayAttr(offVal)); ++tupIdx; offset = mem->offset() + mem->size(); } } } LLVM_DEBUG(llvm::dbgs() << "}\n"); - builder.create(loc, cb); + fir::HasValueOp::create(builder, loc, cb); }; createGlobalInitialization(builder, global, initFunc); } @@ -1696,8 +1721,8 @@ mlir::Value Fortran::lower::genCommonBlockMember( mlir::Value offs = builder.createIntegerConstant(loc, builder.getIndexType(), byteOffset); - mlir::Value varAddr = builder.create( - loc, i8Ptr, base, mlir::ValueRange{offs}); + mlir::Value varAddr = fir::CoordinateOp::create(builder, loc, i8Ptr, base, + mlir::ValueRange{offs}); mlir::Type symType = converter.genType(sym); return Fortran::semantics::FindEquivalenceSet(sym) != nullptr @@ -1722,8 +1747,8 @@ static void instantiateCommon(Fortran::lower::AbstractConverter &converter, if (!commonAddr) { // introduce a local AddrOf and add it to the map fir::GlobalOp global = getCommonBlockGlobal(converter, common); - commonAddr = builder.create(loc, global.resultType(), - global.getSymbol()); + commonAddr = fir::AddrOfOp::create(builder, loc, global.resultType(), + global.getSymbol()); symMap.addSymbol(common, commonAddr); } @@ -2005,8 +2030,8 @@ static void genDeclareSymbol(Fortran::lower::AbstractConverter &converter, Fortran::semantics::GetCUDADataAttr(&sym.GetUltimate())); // Declare a local pointer variable. - auto newBase = builder.create( - loc, boxAlloc, name, /*shape=*/nullptr, lenParams, + auto newBase = hlfir::DeclareOp::create( + builder, loc, boxAlloc, name, /*shape=*/nullptr, lenParams, /*dummy_scope=*/nullptr, attributes); mlir::Value nullAddr = builder.createNullConstant( loc, llvm::cast(ptrBoxType).getEleTy()); @@ -2021,9 +2046,9 @@ static void genDeclareSymbol(Fortran::lower::AbstractConverter &converter, // Inherit the shape (and maybe length parameters) from the pointee // declaration. mlir::Value initVal = - builder.create(loc, ptrBoxType, nullAddr, shapeOrShift, - /*slice=*/nullptr, lenParams); - builder.create(loc, initVal, newBase.getBase()); + fir::EmboxOp::create(builder, loc, ptrBoxType, nullAddr, shapeOrShift, + /*slice=*/nullptr, lenParams); + fir::StoreOp::create(builder, loc, initVal, newBase.getBase()); // Any reference to the pointee is going to be using the pointer // box from now on. The base_addr of the descriptor must be updated @@ -2037,9 +2062,9 @@ static void genDeclareSymbol(Fortran::lower::AbstractConverter &converter, mlir::Value dummyScope; if (converter.isRegisteredDummySymbol(sym)) dummyScope = converter.dummyArgsScopeValue(); - auto newBase = builder.create( - loc, base, name, shapeOrShift, lenParams, dummyScope, attributes, - dataAttr); + auto newBase = + hlfir::DeclareOp::create(builder, loc, base, name, shapeOrShift, + lenParams, dummyScope, attributes, dataAttr); symMap.addVariableDefinition(sym, newBase, force); return; } @@ -2188,7 +2213,7 @@ void Fortran::lower::mapSymbolAttributes( // Additional discussion below. mlir::Type dummyProcType = Fortran::lower::getDummyProcedureType(sym, converter); - mlir::Value undefOp = builder.create(loc, dummyProcType); + mlir::Value undefOp = fir::UndefOp::create(builder, loc, dummyProcType); Fortran::lower::genDeclareSymbol(converter, symMap, sym, undefOp); } @@ -2278,32 +2303,32 @@ void Fortran::lower::mapSymbolAttributes( mlir::Type lenType = builder.getCharacterLengthType(); mlir::Value addr, len; if (Fortran::semantics::IsOptional(sym)) { - auto isPresent = builder.create( - loc, builder.getI1Type(), dummyArg); + auto isPresent = fir::IsPresentOp::create( + builder, loc, builder.getI1Type(), dummyArg); auto addrAndLen = builder .genIfOp(loc, {refTy, lenType}, isPresent, /*withElseRegion=*/true) .genThen([&]() { mlir::Value readAddr = - builder.create(loc, refTy, dummyArg); + fir::BoxAddrOp::create(builder, loc, refTy, dummyArg); mlir::Value readLength = charHelp.readLengthFromBox(dummyArg); - builder.create( - loc, mlir::ValueRange{readAddr, readLength}); + fir::ResultOp::create( + builder, loc, mlir::ValueRange{readAddr, readLength}); }) .genElse([&] { mlir::Value readAddr = builder.genAbsentOp(loc, refTy); mlir::Value readLength = fir::factory::createZeroValue(builder, loc, lenType); - builder.create( - loc, mlir::ValueRange{readAddr, readLength}); + fir::ResultOp::create( + builder, loc, mlir::ValueRange{readAddr, readLength}); }) .getResults(); addr = addrAndLen[0]; len = addrAndLen[1]; } else { - addr = builder.create(loc, refTy, dummyArg); + addr = fir::BoxAddrOp::create(builder, loc, refTy, dummyArg); len = charHelp.readLengthFromBox(dummyArg); } if (!explicitParams.empty()) @@ -2402,7 +2427,7 @@ void Fortran::lower::mapSymbolAttributes( mlir::Value dim = builder.createIntegerConstant(loc, idxTy, iter.index()); auto dimInfo = - builder.create(loc, idxTy, idxTy, idxTy, box, dim); + fir::BoxDimsOp::create(builder, loc, idxTy, idxTy, idxTy, box, dim); shapes.emplace_back(dimInfo.getResult(1)); } else if (spec->ubound().isStar()) { shapes.emplace_back(getAssumedSizeExtent(loc, builder)); @@ -2426,7 +2451,7 @@ void Fortran::lower::mapSymbolAttributes( mlir::Value dim = builder.createIntegerConstant(loc, idxTy, iter.index()); dimInfo = - builder.create(loc, idxTy, idxTy, idxTy, box, dim); + fir::BoxDimsOp::create(builder, loc, idxTy, idxTy, idxTy, box, dim); extents.emplace_back(dimInfo.getResult(1)); if (auto low = spec->lbound().GetExplicit()) { auto expr = Fortran::lower::SomeExpr{*low}; @@ -2475,7 +2500,7 @@ void Fortran::lower::mapSymbolAttributes( if (auto boxTy = mlir::dyn_cast(arg.getType())) { // Contiguous assumed shape that can be tracked without a fir.box. mlir::Type refTy = builder.getRefType(boxTy.getEleTy()); - addr = builder.create(loc, refTy, arg); + addr = fir::BoxAddrOp::create(builder, loc, refTy, arg); } // Compute/Extract character length. @@ -2486,8 +2511,8 @@ void Fortran::lower::mapSymbolAttributes( std::tie(addr, len) = charHelp.createUnboxChar(arg); } else if (mlir::isa(arg.getType())) { // fir.char<1> passed by value (BIND(C) with VALUE attribute). - addr = builder.create(loc, arg.getType()); - builder.create(loc, arg, addr); + addr = fir::AllocaOp::create(builder, loc, arg.getType()); + fir::StoreOp::create(builder, loc, arg, addr); } else if (!addr) { addr = arg; } @@ -2557,7 +2582,7 @@ void Fortran::lower::mapSymbolAttributes( // Dummy argument passed in register. Place the value in memory at that // point since lowering expect symbols to be mapped to memory addresses. mlir::Type symType = converter.genType(sym); - addr = builder.create(loc, symType); + addr = fir::AllocaOp::create(builder, loc, symType); if (isCptrByVal) { // Place the void* address into the CPTR address component. mlir::Value addrComponent = @@ -2777,8 +2802,8 @@ Fortran::lower::genPackArray(Fortran::lower::AbstractConverter &converter, mlir::Type elementType = boxType.unwrapInnerType(); llvm::SmallVector elidedLenParams = fir::factory::elideLengthsAlreadyInType(elementType, lenParams); - auto packOp = builder.create( - loc, fir::getBase(exv), stackAlloc, isInnermostMode, noCopy, + auto packOp = fir::PackArrayOp::create( + builder, loc, fir::getBase(exv), stackAlloc, isInnermostMode, noCopy, /*max_size=*/mlir::IntegerAttr{}, /*max_element_size=*/mlir::IntegerAttr{}, /*min_stride=*/mlir::IntegerAttr{}, fir::PackArrayHeuristics::None, @@ -2816,6 +2841,6 @@ void Fortran::lower::genUnpackArray( // Avoid copy-out for 'intent(in)' variables. bool noCopy = Fortran::semantics::IsIntentIn(sym); fir::FirOpBuilder &builder = converter.getFirOpBuilder(); - builder.create(loc, temp, original, stackAlloc, noCopy, - getSafeRepackAttrs(converter)); + fir::UnpackArrayOp::create(builder, loc, temp, original, stackAlloc, noCopy, + getSafeRepackAttrs(converter)); } diff --git a/flang/lib/Lower/CustomIntrinsicCall.cpp b/flang/lib/Lower/CustomIntrinsicCall.cpp index 30c6ce7f53b3f..2c5233bdd15ee 100644 --- a/flang/lib/Lower/CustomIntrinsicCall.cpp +++ b/flang/lib/Lower/CustomIntrinsicCall.cpp @@ -101,7 +101,7 @@ Fortran::lower::genIntrinsicCall(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value addr = fir::getBase(result); if (auto *box = result.getBoxOf()) addr = - builder.create(loc, box->getMemTy(), box->getAddr()); + fir::BoxAddrOp::create(builder, loc, box->getMemTy(), box->getAddr()); fir::FirOpBuilder *bldr = &builder; stmtCtx.attachCleanup([=]() { bldr->create(loc, addr); }); } @@ -171,9 +171,9 @@ lowerMinOrMax(fir::FirOpBuilder &builder, mlir::Location loc, args.emplace_back(getOperand(opIndex, loadOperand)); fir::ExtendedValue newExtremum = genIntrinsicCall( builder, loc, name, resultType, args, stmtCtx); - builder.create(loc, fir::getBase(newExtremum)); + fir::ResultOp::create(builder, loc, fir::getBase(newExtremum)); }) - .genElse([&]() { builder.create(loc, extremum); }) + .genElse([&]() { fir::ResultOp::create(builder, loc, extremum); }) .getResults()[0]; } else { // Argument is know to be present at compile time. @@ -235,13 +235,13 @@ lowerIshftc(fir::FirOpBuilder &builder, mlir::Location loc, fir::ExtendedValue sizeExv = getOperand(2, loadOperand); mlir::Value size = builder.createConvert(loc, resultType, fir::getBase(sizeExv)); - builder.create(loc, size); + fir::ResultOp::create(builder, loc, size); }) .genElse([&]() { mlir::Value bitSize = builder.createIntegerConstant( loc, resultType, mlir::cast(resultType).getWidth()); - builder.create(loc, bitSize); + fir::ResultOp::create(builder, loc, bitSize); }) .getResults()[0]); return genIntrinsicCall(builder, loc, name, resultType, args, stmtCtx); @@ -280,7 +280,7 @@ lowerAssociated(fir::FirOpBuilder &builder, mlir::Location loc, // while the optionality of the target pointer/allocatable is what must be // checked here. mlir::Value isPresent = - builder.create(loc, builder.getI1Type(), targetBase); + fir::IsPresentOp::create(builder, loc, builder.getI1Type(), targetBase); mlir::Type targetType = fir::unwrapRefType(targetBase.getType()); mlir::Type targetValueType = fir::unwrapPassByRefType(targetType); mlir::Type boxType = mlir::isa(targetType) @@ -293,11 +293,12 @@ lowerAssociated(fir::FirOpBuilder &builder, mlir::Location loc, .genThen([&]() { mlir::Value box = builder.createBox(loc, targetExv); mlir::Value cast = builder.createConvert(loc, boxType, box); - builder.create(loc, cast); + fir::ResultOp::create(builder, loc, cast); }) .genElse([&]() { - mlir::Value absentBox = builder.create(loc, boxType); - builder.create(loc, absentBox); + mlir::Value absentBox = + fir::AbsentOp::create(builder, loc, boxType); + fir::ResultOp::create(builder, loc, absentBox); }) .getResults()[0]; args.emplace_back(std::move(targetBox)); diff --git a/flang/lib/Lower/HlfirIntrinsics.cpp b/flang/lib/Lower/HlfirIntrinsics.cpp index 8b96b209ddb00..6e1d06a25924b 100644 --- a/flang/lib/Lower/HlfirIntrinsics.cpp +++ b/flang/lib/Lower/HlfirIntrinsics.cpp @@ -63,7 +63,7 @@ class HlfirTransformationalIntrinsic { template inline OP createOp(BUILD_ARGS... args) { - return builder.create(loc, args...); + return OP::create(builder, loc, args...); } mlir::Value loadBoxAddress( @@ -195,7 +195,7 @@ mlir::Value HlfirTransformationalIntrinsic::loadBoxAddress( // this is a box address type but is not dynamically optional. Just load // the box, assuming it is well formed (!fir.ref> -> // !fir.box<...>) - return builder.create(loc, actual.getBase()); + return fir::LoadOp::create(builder, loc, actual.getBase()); } return actual; } @@ -209,9 +209,9 @@ mlir::Value HlfirTransformationalIntrinsic::loadBoxAddress( // ensures it won't be. mlir::Value box = builder.createBox(loc, exv); mlir::Type boxType = box.getType(); - auto absent = builder.create(loc, boxType); - auto boxOrAbsent = builder.create( - loc, boxType, isPresent, box, absent); + auto absent = fir::AbsentOp::create(builder, loc, boxType); + auto boxOrAbsent = mlir::arith::SelectOp::create(builder, loc, boxType, + isPresent, box, absent); return boxOrAbsent; } @@ -232,11 +232,11 @@ static mlir::Value loadOptionalValue( assert(actual.isScalar() && fir::isa_trivial(eleType) && "must be a numerical or logical scalar"); hlfir::Entity val = hlfir::loadTrivialScalar(loc, builder, actual); - builder.create(loc, val); + fir::ResultOp::create(builder, loc, val); }) .genElse([&]() { mlir::Value zero = fir::factory::createZeroValue(builder, loc, eleType); - builder.create(loc, zero); + fir::ResultOp::create(builder, loc, zero); }) .getResults()[0]; } diff --git a/flang/lib/Lower/HostAssociations.cpp b/flang/lib/Lower/HostAssociations.cpp index 6a44be65a6cde..2a330ccc4eebb 100644 --- a/flang/lib/Lower/HostAssociations.cpp +++ b/flang/lib/Lower/HostAssociations.cpp @@ -165,7 +165,7 @@ class CapturedSimpleScalars : public CapturedSymbols { assert(typeInTuple && "addrInTuple must be an address"); mlir::Value castBox = builder.createConvertWithVolatileCast( args.loc, typeInTuple, fir::getBase(args.hostValue)); - builder.create(args.loc, castBox, args.addrInTuple); + fir::StoreOp::create(builder, args.loc, castBox, args.addrInTuple); } static void getFromTuple(const GetFromTuple &args, @@ -196,7 +196,7 @@ class CapturedProcedure : public CapturedSymbols { assert(typeInTuple && "addrInTuple must be an address"); mlir::Value castBox = builder.createConvertWithVolatileCast( args.loc, typeInTuple, fir::getBase(args.hostValue)); - builder.create(args.loc, castBox, args.addrInTuple); + fir::StoreOp::create(builder, args.loc, castBox, args.addrInTuple); } static void getFromTuple(const GetFromTuple &args, @@ -231,7 +231,7 @@ class CapturedCharacterScalars fir::FirOpBuilder &builder = converter.getFirOpBuilder(); mlir::Value boxchar = fir::factory::CharacterExprHelper(builder, args.loc) .createEmbox(*charBox); - builder.create(args.loc, boxchar, args.addrInTuple); + fir::StoreOp::create(builder, args.loc, boxchar, args.addrInTuple); } static void getFromTuple(const GetFromTuple &args, @@ -269,20 +269,20 @@ class CapturedPolymorphicScalar args.loc, typeInTuple, fir::getBase(args.hostValue)); if (Fortran::semantics::IsOptional(sym)) { auto isPresent = - builder.create(loc, builder.getI1Type(), castBox); + fir::IsPresentOp::create(builder, loc, builder.getI1Type(), castBox); builder.genIfThenElse(loc, isPresent) .genThen([&]() { - builder.create(loc, castBox, args.addrInTuple); + fir::StoreOp::create(builder, loc, castBox, args.addrInTuple); }) .genElse([&]() { mlir::Value null = fir::factory::createUnallocatedBox( builder, loc, typeInTuple, /*nonDeferredParams=*/mlir::ValueRange{}); - builder.create(loc, null, args.addrInTuple); + fir::StoreOp::create(builder, loc, null, args.addrInTuple); }) .end(); } else { - builder.create(loc, castBox, args.addrInTuple); + fir::StoreOp::create(builder, loc, castBox, args.addrInTuple); } } static void getFromTuple(const GetFromTuple &args, @@ -297,11 +297,11 @@ class CapturedPolymorphicScalar auto eleTy = boxTy.getEleTy(); if (!fir::isa_ref_type(eleTy)) eleTy = builder.getRefType(eleTy); - auto addr = builder.create(loc, eleTy, box); + auto addr = fir::BoxAddrOp::create(builder, loc, eleTy, box); mlir::Value isPresent = builder.genIsNotNullAddr(loc, addr); - auto absentBox = builder.create(loc, boxTy); - box = - builder.create(loc, isPresent, box, absentBox); + auto absentBox = fir::AbsentOp::create(builder, loc, boxTy); + box = mlir::arith::SelectOp::create(builder, loc, isPresent, box, + absentBox); } bindCapturedSymbol(sym, box, converter, args.symMap); } @@ -331,7 +331,7 @@ class CapturedAllocatableAndPointer assert(typeInTuple && "addrInTuple must be an address"); mlir::Value castBox = builder.createConvertWithVolatileCast( args.loc, typeInTuple, fir::getBase(args.hostValue)); - builder.create(args.loc, castBox, args.addrInTuple); + fir::StoreOp::create(builder, args.loc, castBox, args.addrInTuple); } static void getFromTuple(const GetFromTuple &args, Fortran::lower::AbstractConverter &converter, @@ -404,21 +404,21 @@ class CapturedArrays : public CapturedSymbols { // done on present optional. For absent optionals, simply create a // disassociated pointer (it is illegal to inquire about lower bounds or // lengths of optional according to 15.5.2.12 3 (9) and 10.1.11 2 (7)b). - auto isPresent = builder.create( - loc, builder.getI1Type(), fir::getBase(args.hostValue)); + auto isPresent = fir::IsPresentOp::create( + builder, loc, builder.getI1Type(), fir::getBase(args.hostValue)); builder.genIfThenElse(loc, isPresent) .genThen([&]() { fir::factory::associateMutableBox(builder, loc, boxInTuple, args.hostValue, - /*lbounds=*/std::nullopt); + /*lbounds=*/{}); }) .genElse([&]() { fir::factory::disassociateMutableBox(builder, loc, boxInTuple); }) .end(); } else { - fir::factory::associateMutableBox( - builder, loc, boxInTuple, args.hostValue, /*lbounds=*/std::nullopt); + fir::factory::associateMutableBox(builder, loc, boxInTuple, + args.hostValue, /*lbounds=*/{}); } } @@ -441,8 +441,8 @@ class CapturedArrays : public CapturedSymbols { const unsigned rank = sym.Rank(); for (unsigned dim = 0; dim < rank; ++dim) { mlir::Value dimVal = builder.createIntegerConstant(loc, idxTy, dim); - auto dims = builder.create(loc, idxTy, idxTy, idxTy, - box, dimVal); + auto dims = fir::BoxDimsOp::create(builder, loc, idxTy, idxTy, idxTy, + box, dimVal); lbounds.emplace_back(dims.getResult(0)); } } @@ -464,11 +464,11 @@ class CapturedArrays : public CapturedSymbols { auto eleTy = boxTy.getEleTy(); if (!fir::isa_ref_type(eleTy)) eleTy = builder.getRefType(eleTy); - auto addr = builder.create(loc, eleTy, box); + auto addr = fir::BoxAddrOp::create(builder, loc, eleTy, box); mlir::Value isPresent = builder.genIsNotNullAddr(loc, addr); - auto absentBox = builder.create(loc, boxTy); - box = builder.create(loc, isPresent, box, - absentBox); + auto absentBox = fir::AbsentOp::create(builder, loc, boxTy); + box = mlir::arith::SelectOp::create(builder, loc, isPresent, box, + absentBox); } fir::BoxValue boxValue(box, lbounds, /*explicitParams=*/{}); bindCapturedSymbol(sym, boxValue, converter, args.symMap); @@ -540,7 +540,7 @@ static mlir::Value genTupleCoor(fir::FirOpBuilder &builder, mlir::Location loc, auto ty = mlir::isa(varTy) ? mlir::Type(fir::LLVMPointerType::get(varTy)) : mlir::Type(builder.getRefType(varTy)); - return builder.create(loc, ty, tupleArg, offset); + return fir::CoordinateOp::create(builder, loc, ty, tupleArg, offset); } void Fortran::lower::HostAssociations::addSymbolsToBind( @@ -572,7 +572,7 @@ void Fortran::lower::HostAssociations::hostProcedureBindings( mlir::TupleType tupTy = unwrapTupleTy(getArgumentType(converter)); fir::FirOpBuilder &builder = converter.getFirOpBuilder(); mlir::Location loc = converter.getCurrentLocation(); - auto hostTuple = builder.create(loc, tupTy); + auto hostTuple = fir::AllocaOp::create(builder, loc, tupTy); mlir::IntegerType offTy = builder.getIntegerType(32); // Walk the list of tupleSymbols and update the pointers in the tuple. @@ -639,7 +639,7 @@ void Fortran::lower::HostAssociations::internalProcedureBindings( mlir::Value off = builder.createIntegerConstant(loc, offTy, s.index()); mlir::Type varTy = tupTy.getType(s.index()); mlir::Value eleOff = genTupleCoor(builder, loc, varTy, tupleArg, off); - mlir::Value valueInTuple = builder.create(loc, eleOff); + mlir::Value valueInTuple = fir::LoadOp::create(builder, loc, eleOff); GetFromTuple getFromTuple{symMap, valueInTuple, loc}; walkCaptureCategories(getFromTuple, converter, *s.value()); } diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp index 63a612d7ead61..c95c3404a8e26 100644 --- a/flang/lib/Lower/IO.cpp +++ b/flang/lib/Lower/IO.cpp @@ -153,8 +153,8 @@ static mlir::Value genEndIO(Fortran::lower::AbstractConverter &converter, if (csi.ioMsg) { mlir::func::FuncOp getIoMsg = fir::runtime::getIORuntimeFunc(loc, builder); - builder.create( - loc, getIoMsg, + fir::CallOp::create( + builder, loc, getIoMsg, mlir::ValueRange{ cookie, builder.createConvert(loc, getIoMsg.getFunctionType().getInput(1), @@ -164,12 +164,12 @@ static mlir::Value genEndIO(Fortran::lower::AbstractConverter &converter, } mlir::func::FuncOp endIoStatement = fir::runtime::getIORuntimeFunc(loc, builder); - auto call = builder.create(loc, endIoStatement, - mlir::ValueRange{cookie}); + auto call = fir::CallOp::create(builder, loc, endIoStatement, + mlir::ValueRange{cookie}); mlir::Value iostat = call.getResult(0); if (csi.bigUnitIfOp) { stmtCtx.finalizeAndPop(); - builder.create(loc, iostat); + fir::ResultOp::create(builder, loc, iostat); builder.setInsertionPointAfter(csi.bigUnitIfOp); iostat = csi.bigUnitIfOp.getResult(0); } @@ -178,7 +178,7 @@ static mlir::Value genEndIO(Fortran::lower::AbstractConverter &converter, fir::getBase(converter.genExprAddr(loc, csi.ioStatExpr, stmtCtx)); mlir::Value ioStatResult = builder.createConvert(loc, converter.genType(*csi.ioStatExpr), iostat); - builder.create(loc, ioStatResult, ioStatVar); + fir::StoreOp::create(builder, loc, ioStatResult, ioStatVar); } return csi.hasTransferConditionSpec() ? iostat : mlir::Value{}; } @@ -203,8 +203,8 @@ static void makeNextConditionalOn(fir::FirOpBuilder &builder, mlir::IntegerType boolTy = builder.getI1Type(); if (inLoop) resTy = boolTy; - auto ifOp = builder.create(loc, resTy, ok, - /*withElseRegion=*/inLoop); + auto ifOp = fir::IfOp::create(builder, loc, resTy, ok, + /*withElseRegion=*/inLoop); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); } @@ -259,31 +259,34 @@ getNonTbpDefinedIoTableAddr(Fortran::lower::AbstractConverter &converter, ? fir::NameUniquer::doGenerated("default" + suffix) : converter.mangleName(suffix); if (auto table = builder.getNamedGlobal(tableMangleName)) - return builder.createConvert( - loc, refTy, - builder.create(loc, table.resultType(), - table.getSymbol())); + return builder.createConvert(loc, refTy, + fir::AddrOfOp::create(builder, loc, + table.resultType(), + table.getSymbol())); mlir::StringAttr linkOnce = builder.createLinkOnceLinkage(); mlir::Type idxTy = builder.getIndexType(); mlir::Type sizeTy = fir::runtime::getModel()(builder.getContext()); mlir::Type intTy = fir::runtime::getModel()(builder.getContext()); + mlir::Type byteTy = + fir::runtime::getModel()(builder.getContext()); mlir::Type boolTy = fir::runtime::getModel()(builder.getContext()); mlir::Type listTy = fir::SequenceType::get( definedIoProcMap.size(), - mlir::TupleType::get(context, {refTy, refTy, intTy, boolTy})); + mlir::TupleType::get(context, {refTy, refTy, intTy, byteTy})); mlir::Type tableTy = mlir::TupleType::get( context, {sizeTy, fir::ReferenceType::get(listTy), boolTy}); // Define the list of NonTbpDefinedIo procedures. bool tableIsLocal = !definedIoProcMap.empty() && hasLocalDefinedIoProc(definedIoProcMap); - mlir::Value listAddr = - tableIsLocal ? builder.create(loc, listTy) : mlir::Value{}; + mlir::Value listAddr = tableIsLocal + ? fir::AllocaOp::create(builder, loc, listTy) + : mlir::Value{}; std::string listMangleName = tableMangleName + ".list"; auto listFunc = [&](fir::FirOpBuilder &builder) { - mlir::Value list = builder.create(loc, listTy); + mlir::Value list = fir::UndefOp::create(builder, loc, listTy); mlir::IntegerAttr intAttr[4]; for (int i = 0; i < 4; ++i) intAttr[i] = builder.getIntegerAttr(idxTy, i); @@ -292,8 +295,8 @@ getNonTbpDefinedIoTableAddr(Fortran::lower::AbstractConverter &converter, int n0 = 0, n1; auto insert = [&](mlir::Value val) { idx[1] = intAttr[n1++]; - list = builder.create(loc, listTy, list, val, - builder.getArrayAttr(idx)); + list = fir::InsertValueOp::create(builder, loc, listTy, list, val, + builder.getArrayAttr(idx)); }; for (auto &iface : definedIoProcMap) { idx[0] = builder.getIntegerAttr(idxTy, n0++); @@ -303,8 +306,8 @@ getNonTbpDefinedIoTableAddr(Fortran::lower::AbstractConverter &converter, std::string dtName = converter.mangleName(dtSym); insert(builder.createConvert( loc, refTy, - builder.create( - loc, fir::ReferenceType::get(converter.genType(dtSym)), + fir::AddrOfOp::create( + builder, loc, fir::ReferenceType::get(converter.genType(dtSym)), builder.getSymbolRefAttr(dtName)))); // defined IO procedure [void (*subroutine)()], may be null const Fortran::semantics::Symbol *procSym = iface.second.subroutine; @@ -314,8 +317,8 @@ getNonTbpDefinedIoTableAddr(Fortran::lower::AbstractConverter &converter, TODO(loc, "defined IO procedure pointers"); } else if (Fortran::semantics::IsDummy(*procSym)) { Fortran::lower::StatementContext stmtCtx; - insert(builder.create( - loc, refTy, + insert(fir::BoxAddrOp::create( + builder, loc, refTy, fir::getBase(converter.genExprAddr( loc, Fortran::lower::SomeExpr{ @@ -328,8 +331,8 @@ getNonTbpDefinedIoTableAddr(Fortran::lower::AbstractConverter &converter, builder.getSymbolRefAttr(procDef.getSymName()); insert(builder.createConvert( loc, refTy, - builder.create(loc, procDef.getFunctionType(), - nameAttr))); + fir::AddrOfOp::create(builder, loc, procDef.getFunctionType(), + nameAttr))); } } else { insert(builder.createNullConstant(loc, refTy)); @@ -339,14 +342,14 @@ getNonTbpDefinedIoTableAddr(Fortran::lower::AbstractConverter &converter, insert(builder.createIntegerConstant( loc, intTy, static_cast(iface.second.definedIo))); // polymorphic flag is set if first defined IO dummy arg is CLASS(T) + // defaultInt8 flag is set if -fdefined-integer-8 // [bool isDtvArgPolymorphic] - insert(builder.createIntegerConstant(loc, boolTy, - iface.second.isDtvArgPolymorphic)); + insert(builder.createIntegerConstant(loc, byteTy, iface.second.flags)); } if (tableIsLocal) - builder.create(loc, list, listAddr); + fir::StoreOp::create(builder, loc, list, listAddr); else - builder.create(loc, list); + fir::HasValueOp::create(builder, loc, list); }; if (!definedIoProcMap.empty()) { if (tableIsLocal) @@ -358,33 +361,34 @@ getNonTbpDefinedIoTableAddr(Fortran::lower::AbstractConverter &converter, // Define the NonTbpDefinedIoTable. mlir::Value tableAddr = tableIsLocal - ? builder.create(loc, tableTy) + ? fir::AllocaOp::create(builder, loc, tableTy) : mlir::Value{}; auto tableFunc = [&](fir::FirOpBuilder &builder) { - mlir::Value table = builder.create(loc, tableTy); + mlir::Value table = fir::UndefOp::create(builder, loc, tableTy); // list item count [std::size_t items] - table = builder.create( - loc, tableTy, table, + table = fir::InsertValueOp::create( + builder, loc, tableTy, table, builder.createIntegerConstant(loc, sizeTy, definedIoProcMap.size()), builder.getArrayAttr(builder.getIntegerAttr(idxTy, 0))); // item list [const NonTbpDefinedIo *item] if (definedIoProcMap.empty()) listAddr = builder.createNullConstant(loc, builder.getRefType(listTy)); else if (fir::GlobalOp list = builder.getNamedGlobal(listMangleName)) - listAddr = builder.create(loc, list.resultType(), - list.getSymbol()); + listAddr = fir::AddrOfOp::create(builder, loc, list.resultType(), + list.getSymbol()); assert(listAddr && "missing namelist object list"); - table = builder.create( - loc, tableTy, table, listAddr, + table = fir::InsertValueOp::create( + builder, loc, tableTy, table, listAddr, builder.getArrayAttr(builder.getIntegerAttr(idxTy, 1))); // [bool ignoreNonTbpEntries] conservatively set to true - table = builder.create( - loc, tableTy, table, builder.createIntegerConstant(loc, boolTy, true), + table = fir::InsertValueOp::create( + builder, loc, tableTy, table, + builder.createIntegerConstant(loc, boolTy, true), builder.getArrayAttr(builder.getIntegerAttr(idxTy, 2))); if (tableIsLocal) - builder.create(loc, table, tableAddr); + fir::StoreOp::create(builder, loc, table, tableAddr); else - builder.create(loc, table); + fir::HasValueOp::create(builder, loc, table); }; if (tableIsLocal) { tableFunc(builder); @@ -392,8 +396,8 @@ getNonTbpDefinedIoTableAddr(Fortran::lower::AbstractConverter &converter, fir::GlobalOp table = builder.createGlobal( loc, tableTy, tableMangleName, /*isConst=*/true, /*isTarget=*/false, tableFunc, linkOnce); - tableAddr = builder.create( - loc, fir::ReferenceType::get(tableTy), table.getSymbol()); + tableAddr = fir::AddrOfOp::create( + builder, loc, fir::ReferenceType::get(tableTy), table.getSymbol()); } assert(tableAddr && "missing NonTbpDefinedIo table result"); return builder.createConvert(loc, refTy, tableAddr); @@ -418,8 +422,8 @@ getNamelistGroup(Fortran::lower::AbstractConverter &converter, mlir::Location loc = converter.getCurrentLocation(); std::string groupMangleName = converter.mangleName(symbol); if (auto group = builder.getNamedGlobal(groupMangleName)) - return builder.create(loc, group.resultType(), - group.getSymbol()); + return fir::AddrOfOp::create(builder, loc, group.resultType(), + group.getSymbol()); const auto &details = symbol.GetUltimate().get(); @@ -466,18 +470,19 @@ getNamelistGroup(Fortran::lower::AbstractConverter &converter, auto descFunc = [&](fir::FirOpBuilder &b) { auto box = Fortran::lower::genInitialDataTarget( converter, loc, boxTy, *expr, /*couldBeInEquivalence=*/true); - b.create(loc, box); + fir::HasValueOp::create(b, loc, box); }; builder.createGlobalConstant(loc, boxTy, mangleName, descFunc, linkOnce); } } // Define the list of Items. - mlir::Value listAddr = - groupIsLocal ? builder.create(loc, listTy) : mlir::Value{}; + mlir::Value listAddr = groupIsLocal + ? fir::AllocaOp::create(builder, loc, listTy) + : mlir::Value{}; std::string listMangleName = groupMangleName + ".list"; auto listFunc = [&](fir::FirOpBuilder &builder) { - mlir::Value list = builder.create(loc, listTy); + mlir::Value list = fir::UndefOp::create(builder, loc, listTy); mlir::IntegerAttr zero = builder.getIntegerAttr(idxTy, 0); mlir::IntegerAttr one = builder.getIntegerAttr(idxTy, 1); llvm::SmallVector idx = {mlir::Attribute{}, @@ -488,14 +493,14 @@ getNamelistGroup(Fortran::lower::AbstractConverter &converter, idx[1] = zero; mlir::Value nameAddr = builder.createConvert(loc, charRefTy, fir::getBase(stringAddress(s))); - list = builder.create(loc, listTy, list, nameAddr, - builder.getArrayAttr(idx)); + list = fir::InsertValueOp::create(builder, loc, listTy, list, nameAddr, + builder.getArrayAttr(idx)); idx[1] = one; mlir::Value descAddr; if (auto desc = builder.getNamedGlobal( Fortran::lower::mangle::globalNamelistDescriptorName(s))) { - descAddr = builder.create(loc, desc.resultType(), - desc.getSymbol()); + descAddr = fir::AddrOfOp::create(builder, loc, desc.resultType(), + desc.getSymbol()); } else if (Fortran::semantics::FindCommonBlockContaining(s) && IsAllocatableOrPointer(s)) { mlir::Type symType = converter.genType(s); @@ -503,8 +508,8 @@ getNamelistGroup(Fortran::lower::AbstractConverter &converter, Fortran::semantics::FindCommonBlockContaining(s); std::string commonBlockName = converter.mangleName(*commonBlockSym); fir::GlobalOp commonGlobal = builder.getNamedGlobal(commonBlockName); - mlir::Value commonBlockAddr = builder.create( - loc, commonGlobal.resultType(), commonGlobal.getSymbol()); + mlir::Value commonBlockAddr = fir::AddrOfOp::create( + builder, loc, commonGlobal.resultType(), commonGlobal.getSymbol()); mlir::IntegerType i8Ty = builder.getIntegerType(8); mlir::Type i8Ptr = builder.getRefType(i8Ty); mlir::Type seqTy = builder.getRefType(builder.getVarLenSeqTy(i8Ty)); @@ -512,8 +517,8 @@ getNamelistGroup(Fortran::lower::AbstractConverter &converter, std::size_t byteOffset = s.GetUltimate().offset(); mlir::Value offs = builder.createIntegerConstant( loc, builder.getIndexType(), byteOffset); - mlir::Value varAddr = builder.create( - loc, i8Ptr, base, mlir::ValueRange{offs}); + mlir::Value varAddr = fir::CoordinateOp::create( + builder, loc, i8Ptr, base, mlir::ValueRange{offs}); descAddr = builder.createConvert(loc, builder.getRefType(symType), varAddr); } else { @@ -526,16 +531,16 @@ getNamelistGroup(Fortran::lower::AbstractConverter &converter, descAddr = builder.createTemporary(loc, boxType); fir::MutableBoxValue box = fir::MutableBoxValue(descAddr, {}, {}); fir::factory::associateMutableBox(builder, loc, box, exv, - /*lbounds=*/std::nullopt); + /*lbounds=*/{}); } descAddr = builder.createConvert(loc, descRefTy, descAddr); - list = builder.create(loc, listTy, list, descAddr, - builder.getArrayAttr(idx)); + list = fir::InsertValueOp::create(builder, loc, listTy, list, descAddr, + builder.getArrayAttr(idx)); } if (groupIsLocal) - builder.create(loc, list, listAddr); + fir::StoreOp::create(builder, loc, list, listAddr); else - builder.create(loc, list); + fir::HasValueOp::create(builder, loc, list); }; if (groupIsLocal) listFunc(builder); @@ -545,39 +550,39 @@ getNamelistGroup(Fortran::lower::AbstractConverter &converter, // Define the group. mlir::Value groupAddr = groupIsLocal - ? builder.create(loc, groupTy) + ? fir::AllocaOp::create(builder, loc, groupTy) : mlir::Value{}; auto groupFunc = [&](fir::FirOpBuilder &builder) { - mlir::Value group = builder.create(loc, groupTy); + mlir::Value group = fir::UndefOp::create(builder, loc, groupTy); // group name [const char *groupName] - group = builder.create( - loc, groupTy, group, + group = fir::InsertValueOp::create( + builder, loc, groupTy, group, builder.createConvert(loc, charRefTy, fir::getBase(stringAddress(symbol))), builder.getArrayAttr(builder.getIntegerAttr(idxTy, 0))); // list item count [std::size_t items] - group = builder.create( - loc, groupTy, group, + group = fir::InsertValueOp::create( + builder, loc, groupTy, group, builder.createIntegerConstant(loc, sizeTy, details.objects().size()), builder.getArrayAttr(builder.getIntegerAttr(idxTy, 1))); // item list [const Item *item] if (fir::GlobalOp list = builder.getNamedGlobal(listMangleName)) - listAddr = builder.create(loc, list.resultType(), - list.getSymbol()); + listAddr = fir::AddrOfOp::create(builder, loc, list.resultType(), + list.getSymbol()); assert(listAddr && "missing namelist object list"); - group = builder.create( - loc, groupTy, group, listAddr, + group = fir::InsertValueOp::create( + builder, loc, groupTy, group, listAddr, builder.getArrayAttr(builder.getIntegerAttr(idxTy, 2))); // non-type-bound defined IO procedures // [const NonTbpDefinedIoTable *nonTbpDefinedIo] - group = builder.create( - loc, groupTy, group, + group = fir::InsertValueOp::create( + builder, loc, groupTy, group, getNonTbpDefinedIoTableAddr(converter, definedIoProcMap), builder.getArrayAttr(builder.getIntegerAttr(idxTy, 3))); if (groupIsLocal) - builder.create(loc, group, groupAddr); + fir::StoreOp::create(builder, loc, group, groupAddr); else - builder.create(loc, group); + fir::HasValueOp::create(builder, loc, group); }; if (groupIsLocal) { groupFunc(builder); @@ -585,8 +590,8 @@ getNamelistGroup(Fortran::lower::AbstractConverter &converter, fir::GlobalOp group = builder.createGlobal( loc, groupTy, groupMangleName, /*isConst=*/true, /*isTarget=*/false, groupFunc, linkOnce); - groupAddr = builder.create(loc, group.resultType(), - group.getSymbol()); + groupAddr = fir::AddrOfOp::create(builder, loc, group.resultType(), + group.getSymbol()); } assert(groupAddr && "missing namelist group result"); return groupAddr; @@ -606,7 +611,7 @@ static void genNamelistIO(Fortran::lower::AbstractConverter &converter, getNamelistGroup(converter, symbol.GetUltimate(), stmtCtx); groupAddr = builder.createConvert(loc, argType, groupAddr); llvm::SmallVector args = {cookie, groupAddr}; - ok = builder.create(loc, funcOp, args).getResult(0); + ok = fir::CallOp::create(builder, loc, funcOp, args).getResult(0); } /// Is \p type a derived type or an array of derived type? @@ -749,7 +754,7 @@ static void genOutputItemList( outputFuncArgs.push_back(itemValue); } } - ok = builder.create(loc, outputFunc, outputFuncArgs) + ok = fir::CallOp::create(builder, loc, outputFunc, outputFuncArgs) .getResult(0); } } @@ -810,12 +815,12 @@ static void boolRefToLogical(mlir::Location loc, fir::FirOpBuilder &builder, mlir::Value addr) { auto boolType = builder.getRefType(builder.getI1Type()); auto boolAddr = builder.createConvert(loc, boolType, addr); - auto boolValue = builder.create(loc, boolAddr); + auto boolValue = fir::LoadOp::create(builder, loc, boolAddr); auto logicalType = fir::unwrapPassByRefType(addr.getType()); // The convert avoid making any assumptions about how LOGICALs are actually // represented (it might end-up being either a signed or zero extension). auto logicalValue = builder.createConvert(loc, logicalType, boolValue); - builder.create(loc, logicalValue, addr); + fir::StoreOp::create(builder, loc, logicalValue, addr); } static mlir::Value @@ -847,12 +852,13 @@ createIoRuntimeCallForItem(Fortran::lower::AbstractConverter &converter, inputFuncArgs.push_back(builder.createConvert( loc, inputFunc.getFunctionType().getInput(2), len)); } else if (mlir::isa(itemTy)) { - inputFuncArgs.push_back(builder.create( - loc, builder.getI32IntegerAttr( - mlir::cast(itemTy).getWidth() / 8))); + inputFuncArgs.push_back(mlir::arith::ConstantOp::create( + builder, loc, + builder.getI32IntegerAttr( + mlir::cast(itemTy).getWidth() / 8))); } } - auto call = builder.create(loc, inputFunc, inputFuncArgs); + auto call = fir::CallOp::create(builder, loc, inputFunc, inputFuncArgs); auto itemAddr = fir::getBase(item); auto itemTy = fir::unwrapRefType(itemAddr.getType()); if (mlir::isa(itemTy)) @@ -949,7 +955,7 @@ static void genIoLoop(Fortran::lower::AbstractConverter &converter, mlir::Value stepValue = control.step.has_value() ? genControlValue(*control.step) - : builder.create(loc, 1); + : mlir::arith::ConstantIndexOp::create(builder, loc, 1); auto genItemList = [&](const D &ioImpliedDo) { if constexpr (std::is_same_v) genInputItemList(converter, cookie, itemList, isFormatted, checkResult, @@ -960,35 +966,36 @@ static void genIoLoop(Fortran::lower::AbstractConverter &converter, }; if (!checkResult) { // No IO call result checks - the loop is a fir.do_loop op. - auto doLoopOp = builder.create( - loc, lowerValue, upperValue, stepValue, /*unordered=*/false, - /*finalCountValue=*/true); + auto doLoopOp = fir::DoLoopOp::create(builder, loc, lowerValue, upperValue, + stepValue, /*unordered=*/false, + /*finalCountValue=*/true); builder.setInsertionPointToStart(doLoopOp.getBody()); mlir::Value lcv = builder.createConvert( loc, fir::unwrapRefType(loopVar.getType()), doLoopOp.getInductionVar()); - builder.create(loc, lcv, loopVar); + fir::StoreOp::create(builder, loc, lcv, loopVar); genItemList(ioImpliedDo); builder.setInsertionPointToEnd(doLoopOp.getBody()); - mlir::Value result = builder.create( - loc, doLoopOp.getInductionVar(), doLoopOp.getStep(), iofAttr); - builder.create(loc, result); + mlir::Value result = mlir::arith::AddIOp::create( + builder, loc, doLoopOp.getInductionVar(), doLoopOp.getStep(), iofAttr); + fir::ResultOp::create(builder, loc, result); builder.setInsertionPointAfter(doLoopOp); // The loop control variable may be used after the loop. lcv = builder.createConvert(loc, fir::unwrapRefType(loopVar.getType()), doLoopOp.getResult(0)); - builder.create(loc, lcv, loopVar); + fir::StoreOp::create(builder, loc, lcv, loopVar); return; } // Check IO call results - the loop is a fir.iterate_while op. if (!ok) ok = builder.createBool(loc, true); - auto iterWhileOp = builder.create( - loc, lowerValue, upperValue, stepValue, ok, /*finalCountValue*/ true); + auto iterWhileOp = + fir::IterWhileOp::create(builder, loc, lowerValue, upperValue, stepValue, + ok, /*finalCountValue*/ true); builder.setInsertionPointToStart(iterWhileOp.getBody()); mlir::Value lcv = builder.createConvert(loc, fir::unwrapRefType(loopVar.getType()), iterWhileOp.getInductionVar()); - builder.create(loc, lcv, loopVar); + fir::StoreOp::create(builder, loc, lcv, loopVar); ok = iterWhileOp.getIterateVar(); mlir::Value falseValue = builder.createIntegerConstant(loc, builder.getI1Type(), 0); @@ -1001,28 +1008,28 @@ static void genIoLoop(Fortran::lower::AbstractConverter &converter, builder.setInsertionPointAfter(lastOp); // The primary ifOp result is the result of an IO call or loop. if (mlir::isa(*lastOp)) - builder.create(loc, lastOp->getResult(0)); + fir::ResultOp::create(builder, loc, lastOp->getResult(0)); else - builder.create(loc, ok); // loop result + fir::ResultOp::create(builder, loc, ok); // loop result // The else branch propagates an early exit false result. builder.setInsertionPointToStart(&ifOp.getElseRegion().front()); - builder.create(loc, falseValue); + fir::ResultOp::create(builder, loc, falseValue); } builder.setInsertionPointToEnd(iterWhileOp.getBody()); mlir::OpResult iterateResult = builder.getBlock()->back().getResult(0); mlir::Value inductionResult0 = iterWhileOp.getInductionVar(); - auto inductionResult1 = builder.create( - loc, inductionResult0, iterWhileOp.getStep(), iofAttr); - auto inductionResult = builder.create( - loc, iterateResult, inductionResult1, inductionResult0); + auto inductionResult1 = mlir::arith::AddIOp::create( + builder, loc, inductionResult0, iterWhileOp.getStep(), iofAttr); + auto inductionResult = mlir::arith::SelectOp::create( + builder, loc, iterateResult, inductionResult1, inductionResult0); llvm::SmallVector results = {inductionResult, iterateResult}; - builder.create(loc, results); + fir::ResultOp::create(builder, loc, results); ok = iterWhileOp.getResult(1); builder.setInsertionPointAfter(iterWhileOp); // The loop control variable may be used after the loop. lcv = builder.createConvert(loc, fir::unwrapRefType(loopVar.getType()), iterWhileOp.getResult(0)); - builder.create(loc, lcv, loopVar); + fir::StoreOp::create(builder, loc, lcv, loopVar); } //===----------------------------------------------------------------------===// @@ -1044,15 +1051,15 @@ static mlir::Value locToLineNo(Fortran::lower::AbstractConverter &converter, static mlir::Value getDefaultScratch(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type toType) { - mlir::Value null = builder.create( - loc, builder.getI64IntegerAttr(0)); + mlir::Value null = mlir::arith::ConstantOp::create( + builder, loc, builder.getI64IntegerAttr(0)); return builder.createConvert(loc, toType, null); } static mlir::Value getDefaultScratchLen(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type toType) { - return builder.create( - loc, builder.getIntegerAttr(toType, 0)); + return mlir::arith::ConstantOp::create(builder, loc, + builder.getIntegerAttr(toType, 0)); } /// Generate a reference to a buffer and the length of buffer given @@ -1103,8 +1110,8 @@ lowerStringLit(Fortran::lower::AbstractConverter &converter, mlir::Location loc, mlir::Value kind; if (ty2) { auto kindVal = expr->GetType().value().kind(); - kind = builder.create( - loc, builder.getIntegerAttr(ty2, kindVal)); + kind = mlir::arith::ConstantOp::create( + builder, loc, builder.getIntegerAttr(ty2, kindVal)); } return {buff, len, kind}; } @@ -1144,7 +1151,7 @@ mlir::Value genIntIOOption(Fortran::lower::AbstractConverter &converter, loc, Fortran::semantics::GetExpr(spec.v), localStatementCtx)); mlir::Value val = builder.createConvert(loc, ioFuncTy.getInput(1), expr); llvm::SmallVector ioArgs = {cookie, val}; - return builder.create(loc, ioFunc, ioArgs).getResult(0); + return fir::CallOp::create(builder, loc, ioFunc, ioArgs).getResult(0); } /// Generic to build a string argument to the runtime. This passes a CHARACTER @@ -1162,7 +1169,7 @@ mlir::Value genCharIOOption(Fortran::lower::AbstractConverter &converter, ioFuncTy.getInput(1), ioFuncTy.getInput(2)); llvm::SmallVector ioArgs = {cookie, std::get<0>(tup), std::get<1>(tup)}; - return builder.create(loc, ioFunc, ioArgs).getResult(0); + return fir::CallOp::create(builder, loc, ioFunc, ioArgs).getResult(0); } template @@ -1195,7 +1202,7 @@ mlir::Value genIOOption( ioFuncTy.getInput(1), ioFuncTy.getInput(2)); llvm::SmallVector ioArgs{cookie, std::get<0>(tup), std::get<1>(tup)}; - return builder.create(loc, ioFunc, ioArgs).getResult(0); + return fir::CallOp::create(builder, loc, ioFunc, ioArgs).getResult(0); } template <> @@ -1260,7 +1267,7 @@ mlir::Value genIOOption( ioFuncTy.getInput(1), ioFuncTy.getInput(2)); llvm::SmallVector ioArgs = {cookie, std::get<0>(tup), std::get<1>(tup)}; - return builder.create(loc, ioFunc, ioArgs).getResult(0); + return fir::CallOp::create(builder, loc, ioFunc, ioArgs).getResult(0); } template <> @@ -1314,7 +1321,7 @@ mlir::Value genIOOption( ioFuncTy.getInput(1), ioFuncTy.getInput(2)); llvm::SmallVector ioArgs = {cookie, std::get<0>(tup), std::get<1>(tup)}; - return builder.create(loc, ioFunc, ioArgs).getResult(0); + return fir::CallOp::create(builder, loc, ioFunc, ioArgs).getResult(0); } template <> @@ -1350,7 +1357,7 @@ static void genIOGetVar(Fortran::lower::AbstractConverter &converter, mlir::func::FuncOp ioFunc = fir::runtime::getIORuntimeFunc(loc, builder); mlir::Value value = - builder.create(loc, ioFunc, mlir::ValueRange{cookie}) + fir::CallOp::create(builder, loc, ioFunc, mlir::ValueRange{cookie}) .getResult(0); Fortran::lower::StatementContext localStatementCtx; fir::ExtendedValue var = converter.genExprAddr( @@ -1478,8 +1485,8 @@ genConditionHandlerCall(Fortran::lower::AbstractConverter &converter, fir::runtime::getIORuntimeFunc(loc, builder); mlir::Type boolType = enableHandlers.getFunctionType().getInput(1); auto boolValue = [&](bool specifierIsPresent) { - return builder.create( - loc, builder.getIntegerAttr(boolType, specifierIsPresent)); + return mlir::arith::ConstantOp::create( + builder, loc, builder.getIntegerAttr(boolType, specifierIsPresent)); }; llvm::SmallVector ioArgs = {cookie, boolValue(csi.ioStatExpr != nullptr), @@ -1487,7 +1494,7 @@ genConditionHandlerCall(Fortran::lower::AbstractConverter &converter, boolValue(csi.hasEnd), boolValue(csi.hasEor), boolValue(csi.ioMsg.has_value())}; - builder.create(loc, enableHandlers, ioArgs); + fir::CallOp::create(builder, loc, enableHandlers, ioArgs); } //===----------------------------------------------------------------------===// @@ -1661,7 +1668,7 @@ lowerReferenceAsStringSelect(Fortran::lower::AbstractConverter &converter, // Pass the format string reference and the string length out of the select // statement. llvm::SmallVector args = {stringRef, stringLen}; - builder.create(loc, endBlock, args); + mlir::cf::BranchOp::create(builder, loc, endBlock, args); // Add block to the list of cases and make a new one. blockList.push_back(block); @@ -1676,13 +1683,13 @@ lowerReferenceAsStringSelect(Fortran::lower::AbstractConverter &converter, builder, loc, "Assigned format variable '" + symbol->name().ToString() + "' has not been assigned a valid format label"); - builder.create(loc); + fir::UnreachableOp::create(builder, loc); blockList.push_back(unitBlock); // Lower the selectOp. builder.setInsertionPointToEnd(startBlock); auto label = fir::getBase(converter.genExprValue(loc, &expr, stmtCtx)); - builder.create(loc, label, indexList, blockList); + fir::SelectOp::create(builder, loc, label, indexList, blockList); builder.setInsertionPointToEnd(endBlock); endBlock->addArgument(strTy, loc); @@ -1812,17 +1819,17 @@ static mlir::Value genIOUnitNumber(Fortran::lower::AbstractConverter &converter, mlir::Value line = locToLineNo(converter, loc, funcTy.getInput(5)); args.push_back(file); args.push_back(line); - auto checkCall = builder.create(loc, check, args); + auto checkCall = fir::CallOp::create(builder, loc, check, args); if (csi.hasErrorConditionSpec()) { mlir::Value iostat = checkCall.getResult(0); mlir::Type iostatTy = iostat.getType(); mlir::Value zero = fir::factory::createZeroValue(builder, loc, iostatTy); - mlir::Value unitIsOK = builder.create( - loc, mlir::arith::CmpIPredicate::eq, iostat, zero); - auto ifOp = builder.create(loc, iostatTy, unitIsOK, - /*withElseRegion=*/true); + mlir::Value unitIsOK = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, iostat, zero); + auto ifOp = fir::IfOp::create(builder, loc, iostatTy, unitIsOK, + /*withElseRegion=*/true); builder.setInsertionPointToStart(&ifOp.getElseRegion().front()); - builder.create(loc, iostat); + fir::ResultOp::create(builder, loc, iostat); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); stmtCtx.pushScope(); csi.bigUnitIfOp = ifOp; @@ -1844,8 +1851,8 @@ static mlir::Value genIOUnit(Fortran::lower::AbstractConverter &converter, &iounit->u)) return genIOUnitNumber(converter, loc, Fortran::semantics::GetExpr(*e), ty, csi, stmtCtx); - return builder.create( - loc, builder.getIntegerAttr(ty, defaultUnitNumber)); + return mlir::arith::ConstantOp::create( + builder, loc, builder.getIntegerAttr(ty, defaultUnitNumber)); } template @@ -1877,8 +1884,8 @@ static mlir::Value genBasicIOStmt(Fortran::lower::AbstractConverter &converter, mlir::Value un = builder.createConvert(loc, beginFuncTy.getInput(0), unit); mlir::Value file = locToFilename(converter, loc, beginFuncTy.getInput(1)); mlir::Value line = locToLineNo(converter, loc, beginFuncTy.getInput(2)); - auto call = builder.create(loc, beginFunc, - mlir::ValueRange{un, file, line}); + auto call = fir::CallOp::create(builder, loc, beginFunc, + mlir::ValueRange{un, file, line}); mlir::Value cookie = call.getResult(0); genConditionHandlerCall(converter, loc, cookie, stmt.v, csi); mlir::Value ok; @@ -1932,7 +1939,7 @@ genNewunitSpec(Fortran::lower::AbstractConverter &converter, mlir::Location loc, auto kind = builder.createIntegerConstant(loc, ioFuncTy.getInput(2), var->GetType().value().kind()); llvm::SmallVector ioArgs = {cookie, addr, kind}; - return builder.create(loc, ioFunc, ioArgs).getResult(0); + return fir::CallOp::create(builder, loc, ioFunc, ioArgs).getResult(0); } llvm_unreachable("missing Newunit spec"); } @@ -1967,7 +1974,7 @@ Fortran::lower::genOpenStatement(Fortran::lower::AbstractConverter &converter, beginArgs.push_back(locToLineNo(converter, loc, beginFuncTy.getInput(1))); } auto cookie = - builder.create(loc, beginFunc, beginArgs).getResult(0); + fir::CallOp::create(builder, loc, beginFunc, beginArgs).getResult(0); genConditionHandlerCall(converter, loc, cookie, stmt.v, csi); mlir::Value ok; auto insertPt = builder.saveInsertionPoint(); @@ -2011,7 +2018,7 @@ Fortran::lower::genWaitStatement(Fortran::lower::AbstractConverter &converter, args.push_back(locToFilename(converter, loc, beginFuncTy.getInput(1))); args.push_back(locToLineNo(converter, loc, beginFuncTy.getInput(2))); } - auto cookie = builder.create(loc, beginFunc, args).getResult(0); + auto cookie = fir::CallOp::create(builder, loc, beginFunc, args).getResult(0); genConditionHandlerCall(converter, loc, cookie, stmt.v, csi); return genEndIO(converter, converter.getCurrentLocation(), cookie, csi, stmtCtx); @@ -2147,9 +2154,10 @@ void genBeginDataTransferCallArgs( } } else { // PRINT - maybe explicit format; default unit maybeGetFormatArgs(); - ioArgs.push_back(builder.create( - loc, builder.getIntegerAttr(ioFuncTy.getInput(ioArgs.size()), - defaultUnitNumber))); + ioArgs.push_back(mlir::arith::ConstantOp::create( + builder, loc, + builder.getIntegerAttr(ioFuncTy.getInput(ioArgs.size()), + defaultUnitNumber))); } // File name and line number are always the last two arguments. ioArgs.push_back( @@ -2196,7 +2204,7 @@ genDataTransferStmt(Fortran::lower::AbstractConverter &converter, ioArgs, converter, loc, stmt, ioFunc.getFunctionType(), isFormatted, isList || isNml, isInternal, descRef, csi, stmtCtx); mlir::Value cookie = - builder.create(loc, ioFunc, ioArgs).getResult(0); + fir::CallOp::create(builder, loc, ioFunc, ioArgs).getResult(0); auto insertPt = builder.saveInsertionPoint(); mlir::Value ok; @@ -2330,7 +2338,7 @@ mlir::Value genInquireSpec( .c_str())), builder.createConvert(loc, specFuncTy.getInput(2), fir::getBase(str)), builder.createConvert(loc, specFuncTy.getInput(3), fir::getLen(str))}; - return builder.create(loc, specFunc, args).getResult(0); + return fir::CallOp::create(builder, loc, specFunc, args).getResult(0); } /// Specialization for INTEGER. template <> @@ -2367,7 +2375,7 @@ mlir::Value genInquireSpec( .c_str())), builder.createConvert(loc, specFuncTy.getInput(2), addr), builder.createConvert(loc, specFuncTy.getInput(3), kind)}; - return builder.create(loc, specFunc, args).getResult(0); + return fir::CallOp::create(builder, loc, specFunc, args).getResult(0); } /// Specialization for LOGICAL and (PENDING + ID). template <> @@ -2404,7 +2412,7 @@ mlir::Value genInquireSpec( Fortran::parser::InquireSpec::LogVar::EnumToString(logVarKind)} .c_str()))); args.push_back(builder.createConvert(loc, specFuncTy.getInput(2), addr)); - auto call = builder.create(loc, specFunc, args); + auto call = fir::CallOp::create(builder, loc, specFunc, args); boolRefToLogical(loc, builder, addr); return call.getResult(0); } @@ -2500,7 +2508,7 @@ mlir::Value Fortran::lower::genInquireStatement( beginArgs = {locToFilename(converter, loc, beginFuncTy.getInput(0)), locToLineNo(converter, loc, beginFuncTy.getInput(1))}; auto cookie = - builder.create(loc, beginFunc, beginArgs).getResult(0); + fir::CallOp::create(builder, loc, beginFunc, beginArgs).getResult(0); mlir::Value ok; genOutputItemList( converter, cookie, @@ -2521,14 +2529,14 @@ mlir::Value Fortran::lower::genInquireStatement( .getResult(0); mlir::Value length1 = builder.createConvert(loc, converter.genType(*ioLengthVar), length); - builder.create(loc, length1, ioLengthVarAddr); + fir::StoreOp::create(builder, loc, length1, ioLengthVarAddr); return genEndIO(converter, loc, cookie, csi, stmtCtx); } // Common handling for inquire by unit or file. assert(list && "inquire-spec list must be present"); auto cookie = - builder.create(loc, beginFunc, beginArgs).getResult(0); + fir::CallOp::create(builder, loc, beginFunc, beginArgs).getResult(0); genConditionHandlerCall(converter, loc, cookie, *list, csi); // Handle remaining arguments in specifier list. mlir::Value ok; diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index 39e4444cde4e3..471f3685974cd 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -132,21 +132,21 @@ createDataEntryOp(fir::FirOpBuilder &builder, mlir::Location loc, /*withElseRegion=*/true) .genThen([&]() { if (fir::isBoxAddress(baseAddr.getType())) - baseAddr = builder.create(loc, baseAddr); + baseAddr = fir::LoadOp::create(builder, loc, baseAddr); mlir::Value boxAddr = - builder.create(loc, baseAddr); - builder.create(loc, mlir::ValueRange{boxAddr}); + fir::BoxAddrOp::create(builder, loc, baseAddr); + fir::ResultOp::create(builder, loc, mlir::ValueRange{boxAddr}); }) .genElse([&] { mlir::Value absent = - builder.create(loc, ifRetTy); - builder.create(loc, mlir::ValueRange{absent}); + fir::AbsentOp::create(builder, loc, ifRetTy); + fir::ResultOp::create(builder, loc, mlir::ValueRange{absent}); }) .getResults()[0]; } else { if (fir::isBoxAddress(baseAddr.getType())) - baseAddr = builder.create(loc, baseAddr); - baseAddr = builder.create(loc, baseAddr); + baseAddr = fir::LoadOp::create(builder, loc, baseAddr); + baseAddr = fir::BoxAddrOp::create(builder, loc, baseAddr); } retTy = baseAddr.getType(); } @@ -159,7 +159,7 @@ createDataEntryOp(fir::FirOpBuilder &builder, mlir::Location loc, addOperands(operands, operandSegments, bounds); addOperands(operands, operandSegments, async); - Op op = builder.create(loc, retTy, operands); + Op op = Op::create(builder, loc, retTy, operands); op.setNameAttr(builder.getStringAttr(name.str())); op.setStructured(structured); op.setImplicit(implicit); @@ -198,12 +198,12 @@ createDeclareFunc(mlir::OpBuilder &modBuilder, fir::FirOpBuilder &builder, llvm::SmallVector argsTy = {}, llvm::SmallVector locs = {}) { auto funcTy = mlir::FunctionType::get(modBuilder.getContext(), argsTy, {}); - auto funcOp = modBuilder.create(loc, funcName, funcTy); + auto funcOp = mlir::func::FuncOp::create(modBuilder, loc, funcName, funcTy); funcOp.setVisibility(mlir::SymbolTable::Visibility::Private); builder.createBlock(&funcOp.getRegion(), funcOp.getRegion().end(), argsTy, locs); builder.setInsertionPointToEnd(&funcOp.getRegion().back()); - builder.create(loc); + mlir::func::ReturnOp::create(builder, loc); builder.setInsertionPointToStart(&funcOp.getRegion().back()); return funcOp; } @@ -214,7 +214,7 @@ createSimpleOp(fir::FirOpBuilder &builder, mlir::Location loc, const llvm::SmallVectorImpl &operands, const llvm::SmallVectorImpl &operandSegments) { llvm::ArrayRef argTy; - Op op = builder.create(loc, argTy, operands); + Op op = Op::create(builder, loc, argTy, operands); op->setAttr(Op::getOperandSegmentSizeAttr(), builder.getDenseI32ArrayAttr(operandSegments)); return op; @@ -257,15 +257,15 @@ static void createDeclareAllocFuncWithArg(mlir::OpBuilder &modBuilder, if (unwrapFirBox) { mlir::Value desc = - builder.create(loc, registerFuncOp.getArgument(0)); - fir::BoxAddrOp boxAddrOp = builder.create(loc, desc); + fir::LoadOp::create(builder, loc, registerFuncOp.getArgument(0)); + fir::BoxAddrOp boxAddrOp = fir::BoxAddrOp::create(builder, loc, desc); addDeclareAttr(builder, boxAddrOp.getOperation(), clause); EntryOp entryOp = createDataEntryOp( builder, loc, boxAddrOp.getResult(), asFortran, bounds, /*structured=*/false, /*implicit=*/false, clause, boxAddrOp.getType(), /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{}); - builder.create( - loc, mlir::acc::DeclareTokenType::get(entryOp.getContext()), + mlir::acc::DeclareEnterOp::create( + builder, loc, mlir::acc::DeclareTokenType::get(entryOp.getContext()), mlir::ValueRange(entryOp.getAccVar())); } @@ -291,8 +291,8 @@ static void createDeclareDeallocFuncWithArg( mlir::Value var = preDeallocOp.getArgument(0); if (unwrapFirBox) { mlir::Value loadOp = - builder.create(loc, preDeallocOp.getArgument(0)); - fir::BoxAddrOp boxAddrOp = builder.create(loc, loadOp); + fir::LoadOp::create(builder, loc, preDeallocOp.getArgument(0)); + fir::BoxAddrOp boxAddrOp = fir::BoxAddrOp::create(builder, loc, loadOp); addDeclareAttr(builder, boxAddrOp.getOperation(), clause); var = boxAddrOp.getResult(); } @@ -303,25 +303,25 @@ static void createDeclareDeallocFuncWithArg( builder, loc, var, asFortran, bounds, /*structured=*/false, /*implicit=*/false, clause, var.getType(), /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{}); - builder.create( - loc, mlir::Value{}, mlir::ValueRange(entryOp.getAccVar())); + mlir::acc::DeclareExitOp::create(builder, loc, mlir::Value{}, + mlir::ValueRange(entryOp.getAccVar())); if constexpr (std::is_same_v || std::is_same_v) - builder.create(entryOp.getLoc(), entryOp.getAccVar(), - entryOp.getVar(), entryOp.getVarType(), - entryOp.getBounds(), entryOp.getAsyncOperands(), - entryOp.getAsyncOperandsDeviceTypeAttr(), - entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(), - /*structured=*/false, /*implicit=*/false, - builder.getStringAttr(*entryOp.getName())); + ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(), + entryOp.getVar(), entryOp.getVarType(), entryOp.getBounds(), + entryOp.getAsyncOperands(), + entryOp.getAsyncOperandsDeviceTypeAttr(), + entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(), + /*structured=*/false, /*implicit=*/false, + builder.getStringAttr(*entryOp.getName())); else - builder.create(entryOp.getLoc(), entryOp.getAccVar(), - entryOp.getBounds(), entryOp.getAsyncOperands(), - entryOp.getAsyncOperandsDeviceTypeAttr(), - entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(), - /*structured=*/false, /*implicit=*/false, - builder.getStringAttr(*entryOp.getName())); + ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(), + entryOp.getBounds(), entryOp.getAsyncOperands(), + entryOp.getAsyncOperandsDeviceTypeAttr(), + entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(), + /*structured=*/false, /*implicit=*/false, + builder.getStringAttr(*entryOp.getName())); // Generate the post dealloc function. modBuilder.setInsertionPointAfter(preDeallocOp); @@ -333,7 +333,7 @@ static void createDeclareDeallocFuncWithArg( var = postDeallocOp.getArgument(0); if (unwrapFirBox) { - var = builder.create(loc, postDeallocOp.getArgument(0)); + var = fir::LoadOp::create(builder, loc, postDeallocOp.getArgument(0)); asFortran << accFirDescriptorPostfix.str(); } @@ -385,8 +385,8 @@ genAtomicCaptureStatement(Fortran::lower::AbstractConverter &converter, // Generate `atomic.read` operation for atomic assigment statements fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - firOpBuilder.create( - loc, fromAddress, toAddress, mlir::TypeAttr::get(elementType)); + mlir::acc::AtomicReadOp::create(firOpBuilder, loc, fromAddress, toAddress, + mlir::TypeAttr::get(elementType)); } /// Used to generate atomic.write operation which is created in existing @@ -406,7 +406,7 @@ genAtomicWriteStatement(Fortran::lower::AbstractConverter &converter, rhsExpr = firOpBuilder.createConvert(loc, varType, rhsExpr); firOpBuilder.restoreInsertionPoint(insertionPoint); - firOpBuilder.create(loc, lhsAddr, rhsExpr); + mlir::acc::AtomicWriteOp::create(firOpBuilder, loc, lhsAddr, rhsExpr); } /// Used to generate atomic.update operation which is created in existing @@ -522,7 +522,7 @@ static inline void genAtomicUpdateStatement( mlir::Operation *atomicUpdateOp = nullptr; atomicUpdateOp = - firOpBuilder.create(currentLocation, lhsAddr); + mlir::acc::AtomicUpdateOp::create(firOpBuilder, currentLocation, lhsAddr); llvm::SmallVector varTys = {varType}; llvm::SmallVector locs = {currentLocation}; @@ -540,7 +540,7 @@ static inline void genAtomicUpdateStatement( *Fortran::semantics::GetExpr(assignmentStmtExpr), atomicStmtCtx)); mlir::Value convertResult = firOpBuilder.createConvert(currentLocation, varType, rhsExpr); - firOpBuilder.create(currentLocation, convertResult); + mlir::acc::YieldOp::create(firOpBuilder, currentLocation, convertResult); converter.resetExprOverrides(); } firOpBuilder.setInsertionPointAfter(atomicUpdateOp); @@ -647,7 +647,7 @@ void genAtomicCapture(Fortran::lower::AbstractConverter &converter, fir::getBase(converter.genExprValue(assign2.lhs, stmtCtx)).getType(); mlir::Operation *atomicCaptureOp = nullptr; - atomicCaptureOp = firOpBuilder.create(loc); + atomicCaptureOp = mlir::acc::AtomicCaptureOp::create(firOpBuilder, loc); firOpBuilder.createBlock(&(atomicCaptureOp->getRegion(0))); mlir::Block &block = atomicCaptureOp->getRegion(0).back(); @@ -688,7 +688,7 @@ void genAtomicCapture(Fortran::lower::AbstractConverter &converter, loc); } firOpBuilder.setInsertionPointToEnd(&block); - firOpBuilder.create(loc); + mlir::acc::TerminatorOp::create(firOpBuilder, loc); // The clean-ups associated with the statements inside the capture // construct must be generated after the AtomicCaptureOp. firOpBuilder.setInsertionPointAfter(atomicCaptureOp); @@ -708,6 +708,7 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList, bool setDeclareAttr = false) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); Fortran::evaluate::ExpressionAnalyzer ea{semanticsContext}; + const bool unwrapBoxAddr = true; for (const auto &accObject : objectList.v) { llvm::SmallVector bounds; std::stringstream asFortran; @@ -735,8 +736,25 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList, Op op = createDataEntryOp( builder, operandLocation, baseAddr, asFortran, bounds, structured, implicit, dataClause, baseAddr.getType(), async, asyncDeviceTypes, - asyncOnlyDeviceTypes, /*unwrapBoxAddr=*/true, info.isPresent); + asyncOnlyDeviceTypes, unwrapBoxAddr, info.isPresent); dataOperands.push_back(op.getAccVar()); + + // For UseDeviceOp, if operand is one of a pair resulting from a + // declare operation, create a UseDeviceOp for the other operand as well. + if constexpr (std::is_same_v) { + if (auto declareOp = + mlir::dyn_cast(baseAddr.getDefiningOp())) { + mlir::Value otherAddr = declareOp.getResult(1); + if (baseAddr != otherAddr) { + Op op = createDataEntryOp(builder, operandLocation, otherAddr, + asFortran, bounds, structured, implicit, + dataClause, otherAddr.getType(), async, + asyncDeviceTypes, asyncOnlyDeviceTypes, + unwrapBoxAddr, info.isPresent); + dataOperands.push_back(op.getAccVar()); + } + } + } } } @@ -821,15 +839,15 @@ genDataExitOperations(fir::FirOpBuilder &builder, mlir::Location opLoc = exitLoc ? *exitLoc : entryOp.getLoc(); if constexpr (std::is_same_v || std::is_same_v) - builder.create( - opLoc, entryOp.getAccVar(), entryOp.getVar(), entryOp.getVarType(), - entryOp.getBounds(), entryOp.getAsyncOperands(), + ExitOp::create( + builder, opLoc, entryOp.getAccVar(), entryOp.getVar(), + entryOp.getVarType(), entryOp.getBounds(), entryOp.getAsyncOperands(), entryOp.getAsyncOperandsDeviceTypeAttr(), entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(), structured, entryOp.getImplicit(), builder.getStringAttr(*entryOp.getName())); else - builder.create( - opLoc, entryOp.getAccVar(), entryOp.getBounds(), + ExitOp::create( + builder, opLoc, entryOp.getAccVar(), entryOp.getBounds(), entryOp.getAsyncOperands(), entryOp.getAsyncOperandsDeviceTypeAttr(), entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(), structured, entryOp.getImplicit(), builder.getStringAttr(*entryOp.getName())); @@ -841,9 +859,9 @@ fir::ShapeOp genShapeOp(mlir::OpBuilder &builder, fir::SequenceType seqTy, llvm::SmallVector extents; mlir::Type idxTy = builder.getIndexType(); for (auto extent : seqTy.getShape()) - extents.push_back(builder.create( - loc, idxTy, builder.getIntegerAttr(idxTy, extent))); - return builder.create(loc, extents); + extents.push_back(mlir::arith::ConstantOp::create( + builder, loc, idxTy, builder.getIntegerAttr(idxTy, extent))); + return fir::ShapeOp::create(builder, loc, extents); } /// Get the initial value for reduction operator. @@ -918,8 +936,8 @@ static mlir::Value getReductionInitValue(fir::FirOpBuilder &builder, return builder.createBool(loc, value); } if (ty.isIntOrIndex()) - return builder.create( - loc, ty, + return mlir::arith::ConstantOp::create( + builder, loc, ty, builder.getIntegerAttr(ty, getReductionInitValue(op, ty))); if (op == mlir::acc::ReductionOperator::AccMin || op == mlir::acc::ReductionOperator::AccMax) { @@ -927,13 +945,13 @@ static mlir::Value getReductionInitValue(fir::FirOpBuilder &builder, llvm::report_fatal_error( "min/max reduction not supported for complex type"); if (auto floatTy = mlir::dyn_cast_or_null(ty)) - return builder.create( - loc, ty, + return mlir::arith::ConstantOp::create( + builder, loc, ty, builder.getFloatAttr(ty, getReductionInitValue(op, ty))); } else if (auto floatTy = mlir::dyn_cast_or_null(ty)) { - return builder.create( - loc, ty, + return mlir::arith::ConstantOp::create( + builder, loc, ty, builder.getFloatAttr(ty, getReductionInitValue(op, ty))); } else if (auto cmplxTy = mlir::dyn_cast_or_null(ty)) { mlir::Type floatTy = cmplxTy.getElementType(); @@ -967,10 +985,10 @@ static RecipeOp genRecipeOp( mlir::OpBuilder modBuilder(mod.getBodyRegion()); RecipeOp recipe; if constexpr (std::is_same_v) { - recipe = modBuilder.create(loc, recipeName, - ty, op); + recipe = mlir::acc::ReductionRecipeOp::create(modBuilder, loc, recipeName, + ty, op); } else { - recipe = modBuilder.create(loc, recipeName, ty); + recipe = RecipeOp::create(modBuilder, loc, recipeName, ty); } llvm::SmallVector argsTy{ty}; @@ -1014,8 +1032,8 @@ static RecipeOp genRecipeOp( initName, initBlock->getArguments().take_back(initBlock->getArguments().size() - 1), initValue); - builder.create(loc, retVal ? retVal - : initBlock->getArgument(0)); + mlir::acc::YieldOp::create(builder, loc, + retVal ? retVal : initBlock->getArgument(0)); return recipe; } @@ -1114,15 +1132,17 @@ static mlir::Value genShapeFromBoundsOrArgs( mlir::Value zero = builder.createIntegerConstant(loc, idxTy, 0); for (unsigned i = 0; i < args.size(); i += 3) { mlir::Value s1 = - builder.create(loc, args[i + 1], args[0]); - mlir::Value s2 = builder.create(loc, s1, one); - mlir::Value s3 = builder.create(loc, s2, args[i + 2]); - mlir::Value cmp = builder.create( - loc, mlir::arith::CmpIPredicate::sgt, s3, zero); - mlir::Value ext = builder.create(loc, cmp, s3, zero); + mlir::arith::SubIOp::create(builder, loc, args[i + 1], args[0]); + mlir::Value s2 = mlir::arith::AddIOp::create(builder, loc, s1, one); + mlir::Value s3 = + mlir::arith::DivSIOp::create(builder, loc, s2, args[i + 2]); + mlir::Value cmp = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::sgt, s3, zero); + mlir::Value ext = + mlir::arith::SelectOp::create(builder, loc, cmp, s3, zero); extents.push_back(ext); } - return builder.create(loc, extents); + return fir::ShapeOp::create(builder, loc, extents); } static hlfir::DesignateOp::Subscripts @@ -1139,8 +1159,8 @@ static hlfir::Entity genDesignateWithTriplets( hlfir::DesignateOp::Subscripts &triplets, mlir::Value shape) { llvm::SmallVector lenParams; hlfir::genLengthParameters(loc, builder, entity, lenParams); - auto designate = builder.create( - loc, entity.getBase().getType(), entity, /*component=*/"", + auto designate = hlfir::DesignateOp::create( + builder, loc, entity.getBase().getType(), entity, /*component=*/"", /*componentShape=*/mlir::Value{}, triplets, /*substring=*/mlir::ValueRange{}, /*complexPartAttr=*/std::nullopt, shape, lenParams); @@ -1180,22 +1200,22 @@ mlir::acc::FirstprivateRecipeOp Fortran::lower::createOrGetFirstprivateRecipe( builder.setInsertionPointToEnd(&recipe.getCopyRegion().back()); ty = fir::unwrapRefType(ty); if (fir::isa_trivial(ty)) { - mlir::Value initValue = builder.create( - loc, recipe.getCopyRegion().front().getArgument(0)); - builder.create(loc, initValue, - recipe.getCopyRegion().front().getArgument(1)); + mlir::Value initValue = fir::LoadOp::create( + builder, loc, recipe.getCopyRegion().front().getArgument(0)); + fir::StoreOp::create(builder, loc, initValue, + recipe.getCopyRegion().front().getArgument(1)); } else if (auto seqTy = mlir::dyn_cast_or_null(ty)) { fir::FirOpBuilder firBuilder{builder, recipe.getOperation()}; auto shape = genShapeFromBoundsOrArgs( loc, firBuilder, seqTy, bounds, recipe.getCopyRegion().getArguments()); - auto leftDeclOp = builder.create( - loc, recipe.getCopyRegion().getArgument(0), llvm::StringRef{}, shape, - llvm::ArrayRef{}, /*dummy_scope=*/nullptr, + auto leftDeclOp = hlfir::DeclareOp::create( + builder, loc, recipe.getCopyRegion().getArgument(0), llvm::StringRef{}, + shape, llvm::ArrayRef{}, /*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{}); - auto rightDeclOp = builder.create( - loc, recipe.getCopyRegion().getArgument(1), llvm::StringRef{}, shape, - llvm::ArrayRef{}, /*dummy_scope=*/nullptr, + auto rightDeclOp = hlfir::DeclareOp::create( + builder, loc, recipe.getCopyRegion().getArgument(1), llvm::StringRef{}, + shape, llvm::ArrayRef{}, /*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{}); hlfir::DesignateOp::Subscripts triplets = @@ -1207,7 +1227,7 @@ mlir::acc::FirstprivateRecipeOp Fortran::lower::createOrGetFirstprivateRecipe( auto right = genDesignateWithTriplets(firBuilder, loc, rightEntity, triplets, shape); - firBuilder.create(loc, left, right); + hlfir::AssignOp::create(firBuilder, loc, left, right); } else if (auto boxTy = mlir::dyn_cast_or_null(ty)) { fir::FirOpBuilder firBuilder{builder, recipe.getOperation()}; @@ -1228,10 +1248,10 @@ mlir::acc::FirstprivateRecipeOp Fortran::lower::createOrGetFirstprivateRecipe( auto rightEntity = hlfir::Entity{recipe.getCopyRegion().getArgument(1)}; auto right = genDesignateWithTriplets(firBuilder, loc, rightEntity, triplets, shape); - firBuilder.create(loc, left, right); + hlfir::AssignOp::create(firBuilder, loc, left, right); } - builder.create(loc); + mlir::acc::TerminatorOp::create(builder, loc); builder.restoreInsertionPoint(ip); return recipe; } @@ -1396,10 +1416,10 @@ static mlir::Value genLogicalCombiner(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value value1, mlir::Value value2) { mlir::Type i1 = builder.getI1Type(); - mlir::Value v1 = builder.create(loc, i1, value1); - mlir::Value v2 = builder.create(loc, i1, value2); - mlir::Value combined = builder.create(loc, v1, v2); - return builder.create(loc, value1.getType(), combined); + mlir::Value v1 = fir::ConvertOp::create(builder, loc, i1, value1); + mlir::Value v2 = fir::ConvertOp::create(builder, loc, i1, value2); + mlir::Value combined = Op::create(builder, loc, v1, v2); + return fir::ConvertOp::create(builder, loc, value1.getType(), combined); } static mlir::Value genComparisonCombiner(fir::FirOpBuilder &builder, @@ -1408,10 +1428,10 @@ static mlir::Value genComparisonCombiner(fir::FirOpBuilder &builder, mlir::Value value1, mlir::Value value2) { mlir::Type i1 = builder.getI1Type(); - mlir::Value v1 = builder.create(loc, i1, value1); - mlir::Value v2 = builder.create(loc, i1, value2); - mlir::Value add = builder.create(loc, pred, v1, v2); - return builder.create(loc, value1.getType(), add); + mlir::Value v1 = fir::ConvertOp::create(builder, loc, i1, value1); + mlir::Value v2 = fir::ConvertOp::create(builder, loc, i1, value2); + mlir::Value add = mlir::arith::CmpIOp::create(builder, loc, pred, v1, v2); + return fir::ConvertOp::create(builder, loc, value1.getType(), add); } static mlir::Value genScalarCombiner(fir::FirOpBuilder &builder, @@ -1423,21 +1443,21 @@ static mlir::Value genScalarCombiner(fir::FirOpBuilder &builder, value2 = builder.loadIfRef(loc, value2); if (op == mlir::acc::ReductionOperator::AccAdd) { if (ty.isIntOrIndex()) - return builder.create(loc, value1, value2); + return mlir::arith::AddIOp::create(builder, loc, value1, value2); if (mlir::isa(ty)) - return builder.create(loc, value1, value2); + return mlir::arith::AddFOp::create(builder, loc, value1, value2); if (auto cmplxTy = mlir::dyn_cast_or_null(ty)) - return builder.create(loc, value1, value2); + return fir::AddcOp::create(builder, loc, value1, value2); TODO(loc, "reduction add type"); } if (op == mlir::acc::ReductionOperator::AccMul) { if (ty.isIntOrIndex()) - return builder.create(loc, value1, value2); + return mlir::arith::MulIOp::create(builder, loc, value1, value2); if (mlir::isa(ty)) - return builder.create(loc, value1, value2); + return mlir::arith::MulFOp::create(builder, loc, value1, value2); if (mlir::isa(ty)) - return builder.create(loc, value1, value2); + return fir::MulcOp::create(builder, loc, value1, value2); TODO(loc, "reduction mul type"); } @@ -1448,13 +1468,13 @@ static mlir::Value genScalarCombiner(fir::FirOpBuilder &builder, return fir::genMax(builder, loc, {value1, value2}); if (op == mlir::acc::ReductionOperator::AccIand) - return builder.create(loc, value1, value2); + return mlir::arith::AndIOp::create(builder, loc, value1, value2); if (op == mlir::acc::ReductionOperator::AccIor) - return builder.create(loc, value1, value2); + return mlir::arith::OrIOp::create(builder, loc, value1, value2); if (op == mlir::acc::ReductionOperator::AccXor) - return builder.create(loc, value1, value2); + return mlir::arith::XOrIOp::create(builder, loc, value1, value2); if (op == mlir::acc::ReductionOperator::AccLand) return genLogicalCombiner(builder, loc, value1, @@ -1502,19 +1522,21 @@ static void genCombiner(fir::FirOpBuilder &builder, mlir::Location loc, auto shape = genShapeFromBoundsOrArgs(loc, builder, seqTy, bounds, recipe.getCombinerRegion().getArguments()); - auto v1DeclareOp = builder.create( - loc, value1, llvm::StringRef{}, shape, llvm::ArrayRef{}, + auto v1DeclareOp = hlfir::DeclareOp::create( + builder, loc, value1, llvm::StringRef{}, shape, + llvm::ArrayRef{}, /*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{}); - auto v2DeclareOp = builder.create( - loc, value2, llvm::StringRef{}, shape, llvm::ArrayRef{}, + auto v2DeclareOp = hlfir::DeclareOp::create( + builder, loc, value2, llvm::StringRef{}, shape, + llvm::ArrayRef{}, /*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{}); hlfir::DesignateOp::Subscripts triplets = getTripletsFromArgs(recipe); llvm::SmallVector lenParamsLeft; auto leftEntity = hlfir::Entity{v1DeclareOp.getBase()}; hlfir::genLengthParameters(loc, builder, leftEntity, lenParamsLeft); - auto leftDesignate = builder.create( - loc, v1DeclareOp.getBase().getType(), v1DeclareOp.getBase(), + auto leftDesignate = hlfir::DesignateOp::create( + builder, loc, v1DeclareOp.getBase().getType(), v1DeclareOp.getBase(), /*component=*/"", /*componentShape=*/mlir::Value{}, triplets, /*substring=*/mlir::ValueRange{}, /*complexPartAttr=*/std::nullopt, @@ -1524,8 +1546,8 @@ static void genCombiner(fir::FirOpBuilder &builder, mlir::Location loc, llvm::SmallVector lenParamsRight; auto rightEntity = hlfir::Entity{v2DeclareOp.getBase()}; hlfir::genLengthParameters(loc, builder, rightEntity, lenParamsLeft); - auto rightDesignate = builder.create( - loc, v2DeclareOp.getBase().getType(), v2DeclareOp.getBase(), + auto rightDesignate = hlfir::DesignateOp::create( + builder, loc, v2DeclareOp.getBase().getType(), v2DeclareOp.getBase(), /*component=*/"", /*componentShape=*/mlir::Value{}, triplets, /*substring=*/mlir::ValueRange{}, /*complexPartAttr=*/std::nullopt, @@ -1546,21 +1568,21 @@ static void genCombiner(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value elemental = hlfir::genElementalOp( loc, builder, seqTy.getEleTy(), shape, typeParams, genKernel, /*isUnordered=*/true); - builder.create(loc, elemental, v1DeclareOp.getBase()); + hlfir::AssignOp::create(builder, loc, elemental, v1DeclareOp.getBase()); return; } if (bounds.empty()) { llvm::SmallVector extents; mlir::Type idxTy = builder.getIndexType(); for (auto extent : seqTy.getShape()) { - mlir::Value lb = builder.create( - loc, idxTy, builder.getIntegerAttr(idxTy, 0)); - mlir::Value ub = builder.create( - loc, idxTy, builder.getIntegerAttr(idxTy, extent - 1)); - mlir::Value step = builder.create( - loc, idxTy, builder.getIntegerAttr(idxTy, 1)); - auto loop = builder.create(loc, lb, ub, step, - /*unordered=*/false); + mlir::Value lb = mlir::arith::ConstantOp::create( + builder, loc, idxTy, builder.getIntegerAttr(idxTy, 0)); + mlir::Value ub = mlir::arith::ConstantOp::create( + builder, loc, idxTy, builder.getIntegerAttr(idxTy, extent - 1)); + mlir::Value step = mlir::arith::ConstantOp::create( + builder, loc, idxTy, builder.getIntegerAttr(idxTy, 1)); + auto loop = fir::DoLoopOp::create(builder, loc, lb, ub, step, + /*unordered=*/false); builder.setInsertionPointToStart(loop.getBody()); loops.push_back(loop); ivs.push_back(loop.getInductionVar()); @@ -1576,8 +1598,8 @@ static void genCombiner(fir::FirOpBuilder &builder, mlir::Location loc, llvm::SmallVector values = genConstantBounds(builder, loc, dataBound); auto loop = - builder.create(loc, values[0], values[1], values[2], - /*unordered=*/false); + fir::DoLoopOp::create(builder, loc, values[0], values[1], values[2], + /*unordered=*/false); builder.setInsertionPointToStart(loop.getBody()); loops.push_back(loop); ivs.push_back(loop.getInductionVar()); @@ -1593,31 +1615,31 @@ static void genCombiner(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value lb = recipe.getCombinerRegion().getArgument(i); mlir::Value ub = recipe.getCombinerRegion().getArgument(i + 1); mlir::Value step = recipe.getCombinerRegion().getArgument(i + 2); - auto loop = builder.create(loc, lb, ub, step, - /*unordered=*/false); + auto loop = fir::DoLoopOp::create(builder, loc, lb, ub, step, + /*unordered=*/false); builder.setInsertionPointToStart(loop.getBody()); loops.push_back(loop); ivs.push_back(loop.getInductionVar()); } } - auto addr1 = builder.create(loc, refTy, value1, ivs); - auto addr2 = builder.create(loc, refTy, value2, ivs); - auto load1 = builder.create(loc, addr1); - auto load2 = builder.create(loc, addr2); + auto addr1 = fir::CoordinateOp::create(builder, loc, refTy, value1, ivs); + auto addr2 = fir::CoordinateOp::create(builder, loc, refTy, value2, ivs); + auto load1 = fir::LoadOp::create(builder, loc, addr1); + auto load2 = fir::LoadOp::create(builder, loc, addr2); mlir::Value res = genScalarCombiner(builder, loc, op, seqTy.getEleTy(), load1, load2); - builder.create(loc, res, addr1); + fir::StoreOp::create(builder, loc, res, addr1); builder.setInsertionPointAfter(loops[0]); } else if (auto boxTy = mlir::dyn_cast(ty)) { mlir::Type innerTy = fir::unwrapRefType(boxTy.getEleTy()); if (fir::isa_trivial(innerTy)) { mlir::Value boxAddr1 = value1, boxAddr2 = value2; if (fir::isBoxAddress(boxAddr1.getType())) - boxAddr1 = builder.create(loc, boxAddr1); + boxAddr1 = fir::LoadOp::create(builder, loc, boxAddr1); if (fir::isBoxAddress(boxAddr2.getType())) - boxAddr2 = builder.create(loc, boxAddr2); - boxAddr1 = builder.create(loc, boxAddr1); - boxAddr2 = builder.create(loc, boxAddr2); + boxAddr2 = fir::LoadOp::create(builder, loc, boxAddr2); + boxAddr1 = fir::BoxAddrOp::create(builder, loc, boxAddr1); + boxAddr2 = fir::BoxAddrOp::create(builder, loc, boxAddr2); auto leftEntity = hlfir::Entity{boxAddr1}; auto rightEntity = hlfir::Entity{boxAddr2}; @@ -1625,7 +1647,7 @@ static void genCombiner(fir::FirOpBuilder &builder, mlir::Location loc, auto rightVal = hlfir::loadTrivialScalar(loc, builder, rightEntity); mlir::Value res = genScalarCombiner(builder, loc, op, innerTy, leftVal, rightVal); - builder.create(loc, res, boxAddr1); + hlfir::AssignOp::create(builder, loc, res, boxAddr1); } else { mlir::Type innerTy = fir::extractSequenceType(boxTy); fir::SequenceType seqTy = @@ -1640,14 +1662,14 @@ static void genCombiner(fir::FirOpBuilder &builder, mlir::Location loc, getSubscriptsFromArgs(recipe.getCombinerRegion().getArguments()); auto leftEntity = hlfir::Entity{value1}; if (fir::isBoxAddress(value1.getType())) - leftEntity = - hlfir::Entity{builder.create(loc, value1).getResult()}; + leftEntity = hlfir::Entity{ + fir::LoadOp::create(builder, loc, value1).getResult()}; auto left = genDesignateWithTriplets(builder, loc, leftEntity, triplets, shape); auto rightEntity = hlfir::Entity{value2}; if (fir::isBoxAddress(value2.getType())) - rightEntity = - hlfir::Entity{builder.create(loc, value2).getResult()}; + rightEntity = hlfir::Entity{ + fir::LoadOp::create(builder, loc, value2).getResult()}; auto right = genDesignateWithTriplets(builder, loc, rightEntity, triplets, shape); @@ -1665,11 +1687,11 @@ static void genCombiner(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value elemental = hlfir::genElementalOp( loc, builder, seqTy.getEleTy(), shape, typeParams, genKernel, /*isUnordered=*/true); - builder.create(loc, elemental, value1); + hlfir::AssignOp::create(builder, loc, elemental, value1); } } else { mlir::Value res = genScalarCombiner(builder, loc, op, ty, value1, value2); - builder.create(loc, res, value1); + fir::StoreOp::create(builder, loc, res, value1); } } @@ -1711,7 +1733,7 @@ mlir::acc::ReductionRecipeOp Fortran::lower::createOrGetReductionRecipe( mlir::Value v1 = recipe.getCombinerRegion().front().getArgument(0); mlir::Value v2 = recipe.getCombinerRegion().front().getArgument(1); genCombiner(builder, loc, op, ty, v1, v2, recipe, bounds, allConstantBound); - builder.create(loc, v1); + mlir::acc::YieldOp::create(builder, loc, v1); builder.restoreInsertionPoint(ip); return recipe; } @@ -1803,7 +1825,7 @@ createRegionOp(fir::FirOpBuilder &builder, mlir::Location loc, llvm::SmallVector retTy = {}, mlir::Value yieldValue = {}, mlir::TypeRange argsTy = {}, llvm::SmallVector locs = {}) { - Op op = builder.create(loc, retTy, operands); + Op op = Op::create(builder, loc, retTy, operands); builder.createBlock(&op.getRegion(), op.getRegion().end(), argsTy, locs); mlir::Block &block = op.getRegion().back(); builder.setInsertionPointToStart(&block); @@ -1823,13 +1845,13 @@ createRegionOp(fir::FirOpBuilder &builder, mlir::Location loc, if (yieldValue) { if constexpr (std::is_same_v) { - Terminator yieldOp = builder.create(returnLoc, yieldValue); + Terminator yieldOp = Terminator::create(builder, returnLoc, yieldValue); yieldValue.getDefiningOp()->moveBefore(yieldOp); } else { - builder.create(returnLoc); + Terminator::create(builder, returnLoc); } } else { - builder.create(returnLoc); + Terminator::create(builder, returnLoc); } builder.setInsertionPointToStart(&block); return op; @@ -2419,7 +2441,7 @@ static mlir::acc::LoopOp createLoopOp( for (auto [arg, value] : llvm::zip( loopOp.getLoopRegions().front()->front().getArguments(), ivPrivate)) - builder.create(currentLocation, arg, value); + fir::StoreOp::create(builder, currentLocation, arg, value); loopOp.setInclusiveUpperbound(inclusiveBounds); @@ -3732,8 +3754,8 @@ genACCUpdateOp(Fortran::lower::AbstractConverter &converter, dataClauseOperands.append(updateHostOperands); - builder.create( - currentLocation, ifCond, asyncOperands, + mlir::acc::UpdateOp::create( + builder, currentLocation, ifCond, asyncOperands, getArrayAttr(builder, asyncOperandsDeviceTypes), getArrayAttr(builder, asyncOnlyDeviceTypes), waitOperands, getDenseI32ArrayAttr(builder, waitOperandsSegments), @@ -3855,13 +3877,14 @@ static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder, const std::string &declareGlobalName, bool implicit, std::stringstream &asFortran) { GlobalOp declareGlobalOp = - modBuilder.create(loc, declareGlobalName); + GlobalOp::create(modBuilder, loc, declareGlobalName); builder.createBlock(&declareGlobalOp.getRegion(), declareGlobalOp.getRegion().end(), {}, {}); builder.setInsertionPointToEnd(&declareGlobalOp.getRegion().back()); - fir::AddrOfOp addrOp = builder.create( - loc, fir::ReferenceType::get(globalOp.getType()), globalOp.getSymbol()); + fir::AddrOfOp addrOp = fir::AddrOfOp::create( + builder, loc, fir::ReferenceType::get(globalOp.getType()), + globalOp.getSymbol()); addDeclareAttr(builder, addrOp, clause); llvm::SmallVector bounds; @@ -3870,21 +3893,21 @@ static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder, /*structured=*/false, implicit, clause, addrOp.getResTy().getType(), /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{}); if constexpr (std::is_same_v) - builder.create( - loc, mlir::acc::DeclareTokenType::get(entryOp.getContext()), - mlir::ValueRange(entryOp.getAccVar())); + DeclareOp::create(builder, loc, + mlir::acc::DeclareTokenType::get(entryOp.getContext()), + mlir::ValueRange(entryOp.getAccVar())); else - builder.create(loc, mlir::Value{}, - mlir::ValueRange(entryOp.getAccVar())); + DeclareOp::create(builder, loc, mlir::Value{}, + mlir::ValueRange(entryOp.getAccVar())); if constexpr (std::is_same_v) { - builder.create(entryOp.getLoc(), entryOp.getAccVar(), - entryOp.getBounds(), entryOp.getAsyncOperands(), - entryOp.getAsyncOperandsDeviceTypeAttr(), - entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(), - /*structured=*/false, /*implicit=*/false, - builder.getStringAttr(*entryOp.getName())); + ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(), + entryOp.getBounds(), entryOp.getAsyncOperands(), + entryOp.getAsyncOperandsDeviceTypeAttr(), + entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(), + /*structured=*/false, /*implicit=*/false, + builder.getStringAttr(*entryOp.getName())); } - builder.create(loc); + mlir::acc::TerminatorOp::create(builder, loc); modBuilder.setInsertionPointAfter(declareGlobalOp); } @@ -3899,8 +3922,9 @@ static void createDeclareAllocFunc(mlir::OpBuilder &modBuilder, auto registerFuncOp = createDeclareFunc(modBuilder, builder, loc, registerFuncName.str()); - fir::AddrOfOp addrOp = builder.create( - loc, fir::ReferenceType::get(globalOp.getType()), globalOp.getSymbol()); + fir::AddrOfOp addrOp = fir::AddrOfOp::create( + builder, loc, fir::ReferenceType::get(globalOp.getType()), + globalOp.getSymbol()); std::stringstream asFortran; asFortran << Fortran::lower::mangle::demangleName(globalOp.getSymName()); @@ -3923,15 +3947,15 @@ static void createDeclareAllocFunc(mlir::OpBuilder &modBuilder, createSimpleOp(builder, loc, operands, operandSegments); if (unwrapFirBox) { - auto loadOp = builder.create(loc, addrOp.getResult()); - fir::BoxAddrOp boxAddrOp = builder.create(loc, loadOp); + auto loadOp = fir::LoadOp::create(builder, loc, addrOp.getResult()); + fir::BoxAddrOp boxAddrOp = fir::BoxAddrOp::create(builder, loc, loadOp); addDeclareAttr(builder, boxAddrOp.getOperation(), clause); EntryOp entryOp = createDataEntryOp( builder, loc, boxAddrOp.getResult(), asFortran, bounds, /*structured=*/false, /*implicit=*/false, clause, boxAddrOp.getType(), /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{}); - builder.create( - loc, mlir::acc::DeclareTokenType::get(entryOp.getContext()), + mlir::acc::DeclareEnterOp::create( + builder, loc, mlir::acc::DeclareTokenType::get(entryOp.getContext()), mlir::ValueRange(entryOp.getAccVar())); } @@ -3962,10 +3986,11 @@ static void createDeclareDeallocFunc(mlir::OpBuilder &modBuilder, auto preDeallocOp = createDeclareFunc(modBuilder, builder, loc, preDeallocFuncName.str()); - fir::AddrOfOp addrOp = builder.create( - loc, fir::ReferenceType::get(globalOp.getType()), globalOp.getSymbol()); - auto loadOp = builder.create(loc, addrOp.getResult()); - fir::BoxAddrOp boxAddrOp = builder.create(loc, loadOp); + fir::AddrOfOp addrOp = fir::AddrOfOp::create( + builder, loc, fir::ReferenceType::get(globalOp.getType()), + globalOp.getSymbol()); + auto loadOp = fir::LoadOp::create(builder, loc, addrOp.getResult()); + fir::BoxAddrOp boxAddrOp = fir::BoxAddrOp::create(builder, loc, loadOp); mlir::Value var = boxAddrOp.getResult(); addDeclareAttr(builder, var.getDefiningOp(), clause); @@ -3976,25 +4001,25 @@ static void createDeclareDeallocFunc(mlir::OpBuilder &modBuilder, /*structured=*/false, /*implicit=*/false, clause, var.getType(), /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{}); - builder.create( - loc, mlir::Value{}, mlir::ValueRange(entryOp.getAccVar())); + mlir::acc::DeclareExitOp::create(builder, loc, mlir::Value{}, + mlir::ValueRange(entryOp.getAccVar())); if constexpr (std::is_same_v || std::is_same_v) - builder.create( - entryOp.getLoc(), entryOp.getAccVar(), entryOp.getVar(), - entryOp.getBounds(), entryOp.getAsyncOperands(), - entryOp.getAsyncOperandsDeviceTypeAttr(), entryOp.getAsyncOnlyAttr(), - entryOp.getDataClause(), - /*structured=*/false, /*implicit=*/false, - builder.getStringAttr(*entryOp.getName())); + ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(), + entryOp.getVar(), entryOp.getBounds(), + entryOp.getAsyncOperands(), + entryOp.getAsyncOperandsDeviceTypeAttr(), + entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(), + /*structured=*/false, /*implicit=*/false, + builder.getStringAttr(*entryOp.getName())); else - builder.create( - entryOp.getLoc(), entryOp.getAccVar(), entryOp.getBounds(), - entryOp.getAsyncOperands(), entryOp.getAsyncOperandsDeviceTypeAttr(), - entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(), - /*structured=*/false, /*implicit=*/false, - builder.getStringAttr(*entryOp.getName())); + ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(), + entryOp.getBounds(), entryOp.getAsyncOperands(), + entryOp.getAsyncOperandsDeviceTypeAttr(), + entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(), + /*structured=*/false, /*implicit=*/false, + builder.getStringAttr(*entryOp.getName())); // Generate the post dealloc function. modBuilder.setInsertionPointAfter(preDeallocOp); @@ -4006,8 +4031,9 @@ static void createDeclareDeallocFunc(mlir::OpBuilder &modBuilder, auto postDeallocOp = createDeclareFunc(modBuilder, builder, loc, postDeallocFuncName.str()); - fir::AddrOfOp addrOp = builder.create( - loc, fir::ReferenceType::get(globalOp.getType()), globalOp.getSymbol()); + fir::AddrOfOp addrOp = fir::AddrOfOp::create( + builder, loc, fir::ReferenceType::get(globalOp.getType()), + globalOp.getSymbol()); if (unwrapFirBox) asFortran << accFirDescriptorPostfix.str(); llvm::SmallVector bounds; @@ -4244,13 +4270,13 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter, auto ops = funcOp.getOps(); mlir::Value declareToken; if (ops.empty()) { - declareToken = builder.create( - loc, mlir::acc::DeclareTokenType::get(builder.getContext()), + declareToken = mlir::acc::DeclareEnterOp::create( + builder, loc, mlir::acc::DeclareTokenType::get(builder.getContext()), dataClauseOperands); } else { auto declareOp = *ops.begin(); - auto newDeclareOp = builder.create( - loc, mlir::acc::DeclareTokenType::get(builder.getContext()), + auto newDeclareOp = mlir::acc::DeclareEnterOp::create( + builder, loc, mlir::acc::DeclareTokenType::get(builder.getContext()), declareOp.getDataClauseOperands()); newDeclareOp.getDataClauseOperandsMutable().append(dataClauseOperands); declareToken = newDeclareOp.getToken(); @@ -4272,7 +4298,7 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter, mlir::func::FuncOp funcOp = builder.getFunction(); auto ops = funcOp.getOps(); if (ops.empty()) { - builder.create(loc, declareToken, operands); + mlir::acc::DeclareExitOp::create(builder, loc, declareToken, operands); } else { auto declareOp = *ops.begin(); declareOp.getDataClauseOperandsMutable().append(operands); @@ -4396,10 +4422,34 @@ getAttributeValueByDeviceType(llvm::SmallVector &attributes, return std::nullopt; } +// Helper function to extract string value from bind name variant +static std::optional getBindNameStringValue( + const std::optional> + &bindNameValue) { + if (!bindNameValue.has_value()) + return std::nullopt; + + return std::visit( + [](const auto &attr) -> std::optional { + if constexpr (std::is_same_v, + mlir::StringAttr>) { + return attr.getValue(); + } else if constexpr (std::is_same_v, + mlir::SymbolRefAttr>) { + return attr.getLeafReference(); + } else { + return std::nullopt; + } + }, + bindNameValue.value()); +} + static bool compareDeviceTypeInfo( mlir::acc::RoutineOp op, - llvm::SmallVector &bindNameArrayAttr, - llvm::SmallVector &bindNameDeviceTypeArrayAttr, + llvm::SmallVector &bindIdNameArrayAttr, + llvm::SmallVector &bindStrNameArrayAttr, + llvm::SmallVector &bindIdNameDeviceTypeArrayAttr, + llvm::SmallVector &bindStrNameDeviceTypeArrayAttr, llvm::SmallVector &gangArrayAttr, llvm::SmallVector &gangDimArrayAttr, llvm::SmallVector &gangDimDeviceTypeArrayAttr, @@ -4409,9 +4459,13 @@ static bool compareDeviceTypeInfo( for (uint32_t dtypeInt = 0; dtypeInt != mlir::acc::getMaxEnumValForDeviceType(); ++dtypeInt) { auto dtype = static_cast(dtypeInt); - if (op.getBindNameValue(dtype) != - getAttributeValueByDeviceType( - bindNameArrayAttr, bindNameDeviceTypeArrayAttr, dtype)) + auto bindNameValue = getBindNameStringValue(op.getBindNameValue(dtype)); + if (bindNameValue != + getAttributeValueByDeviceType( + bindIdNameArrayAttr, bindIdNameDeviceTypeArrayAttr, dtype) && + bindNameValue != + getAttributeValueByDeviceType( + bindStrNameArrayAttr, bindStrNameDeviceTypeArrayAttr, dtype)) return false; if (op.hasGang(dtype) != hasDeviceType(gangArrayAttr, dtype)) return false; @@ -4458,8 +4512,10 @@ getArrayAttrOrNull(fir::FirOpBuilder &builder, void createOpenACCRoutineConstruct( Fortran::lower::AbstractConverter &converter, mlir::Location loc, mlir::ModuleOp mod, mlir::func::FuncOp funcOp, std::string funcName, - bool hasNohost, llvm::SmallVector &bindNames, - llvm::SmallVector &bindNameDeviceTypes, + bool hasNohost, llvm::SmallVector &bindIdNames, + llvm::SmallVector &bindStrNames, + llvm::SmallVector &bindIdNameDeviceTypes, + llvm::SmallVector &bindStrNameDeviceTypes, llvm::SmallVector &gangDeviceTypes, llvm::SmallVector &gangDimValues, llvm::SmallVector &gangDimDeviceTypes, @@ -4472,7 +4528,8 @@ void createOpenACCRoutineConstruct( 0) { // If the routine is already specified with the same clauses, just skip // the operation creation. - if (compareDeviceTypeInfo(routineOp, bindNames, bindNameDeviceTypes, + if (compareDeviceTypeInfo(routineOp, bindIdNames, bindStrNames, + bindIdNameDeviceTypes, bindStrNameDeviceTypes, gangDeviceTypes, gangDimValues, gangDimDeviceTypes, seqDeviceTypes, workerDeviceTypes, vectorDeviceTypes) && @@ -4486,11 +4543,13 @@ void createOpenACCRoutineConstruct( std::string routineOpStr = routineOpName.str(); mlir::OpBuilder modBuilder(mod.getBodyRegion()); fir::FirOpBuilder &builder = converter.getFirOpBuilder(); - modBuilder.create( - loc, routineOpStr, + mlir::acc::RoutineOp::create( + modBuilder, loc, routineOpStr, mlir::SymbolRefAttr::get(builder.getContext(), funcName), - getArrayAttrOrNull(builder, bindNames), - getArrayAttrOrNull(builder, bindNameDeviceTypes), + getArrayAttrOrNull(builder, bindIdNames), + getArrayAttrOrNull(builder, bindStrNames), + getArrayAttrOrNull(builder, bindIdNameDeviceTypes), + getArrayAttrOrNull(builder, bindStrNameDeviceTypes), getArrayAttrOrNull(builder, workerDeviceTypes), getArrayAttrOrNull(builder, vectorDeviceTypes), getArrayAttrOrNull(builder, seqDeviceTypes), hasNohost, @@ -4507,8 +4566,10 @@ static void interpretRoutineDeviceInfo( llvm::SmallVector &seqDeviceTypes, llvm::SmallVector &vectorDeviceTypes, llvm::SmallVector &workerDeviceTypes, - llvm::SmallVector &bindNameDeviceTypes, - llvm::SmallVector &bindNames, + llvm::SmallVector &bindIdNameDeviceTypes, + llvm::SmallVector &bindStrNameDeviceTypes, + llvm::SmallVector &bindIdNames, + llvm::SmallVector &bindStrNames, llvm::SmallVector &gangDeviceTypes, llvm::SmallVector &gangDimValues, llvm::SmallVector &gangDimDeviceTypes) { @@ -4541,16 +4602,18 @@ static void interpretRoutineDeviceInfo( if (dinfo.bindNameOpt().has_value()) { const auto &bindName = dinfo.bindNameOpt().value(); mlir::Attribute bindNameAttr; - if (const auto &bindStr{std::get_if(&bindName)}) { + if (const auto &bindSym{ + std::get_if(&bindName)}) { + bindNameAttr = builder.getSymbolRefAttr(converter.mangleName(*bindSym)); + bindIdNames.push_back(bindNameAttr); + bindIdNameDeviceTypes.push_back(getDeviceTypeAttr()); + } else if (const auto &bindStr{std::get_if(&bindName)}) { bindNameAttr = builder.getStringAttr(*bindStr); - } else if (const auto &bindSym{ - std::get_if(&bindName)}) { - bindNameAttr = builder.getStringAttr(converter.mangleName(*bindSym)); + bindStrNames.push_back(bindNameAttr); + bindStrNameDeviceTypes.push_back(getDeviceTypeAttr()); } else { llvm_unreachable("Unsupported bind name type"); } - bindNames.push_back(bindNameAttr); - bindNameDeviceTypes.push_back(getDeviceTypeAttr()); } } @@ -4566,8 +4629,9 @@ void Fortran::lower::genOpenACCRoutineConstruct( bool hasNohost{false}; llvm::SmallVector seqDeviceTypes, vectorDeviceTypes, - workerDeviceTypes, bindNameDeviceTypes, bindNames, gangDeviceTypes, - gangDimDeviceTypes, gangDimValues; + workerDeviceTypes, bindIdNameDeviceTypes, bindStrNameDeviceTypes, + bindIdNames, bindStrNames, gangDeviceTypes, gangDimDeviceTypes, + gangDimValues; for (const Fortran::semantics::OpenACCRoutineInfo &info : routineInfos) { // Device Independent Attributes @@ -4576,24 +4640,26 @@ void Fortran::lower::genOpenACCRoutineConstruct( } // Note: Device Independent Attributes are set to the // none device type in `info`. - interpretRoutineDeviceInfo(converter, info, seqDeviceTypes, - vectorDeviceTypes, workerDeviceTypes, - bindNameDeviceTypes, bindNames, gangDeviceTypes, - gangDimValues, gangDimDeviceTypes); + interpretRoutineDeviceInfo( + converter, info, seqDeviceTypes, vectorDeviceTypes, workerDeviceTypes, + bindIdNameDeviceTypes, bindStrNameDeviceTypes, bindIdNames, + bindStrNames, gangDeviceTypes, gangDimValues, gangDimDeviceTypes); // Device Dependent Attributes for (const Fortran::semantics::OpenACCRoutineDeviceTypeInfo &dinfo : info.deviceTypeInfos()) { - interpretRoutineDeviceInfo( - converter, dinfo, seqDeviceTypes, vectorDeviceTypes, - workerDeviceTypes, bindNameDeviceTypes, bindNames, gangDeviceTypes, - gangDimValues, gangDimDeviceTypes); + interpretRoutineDeviceInfo(converter, dinfo, seqDeviceTypes, + vectorDeviceTypes, workerDeviceTypes, + bindIdNameDeviceTypes, bindStrNameDeviceTypes, + bindIdNames, bindStrNames, gangDeviceTypes, + gangDimValues, gangDimDeviceTypes); } } createOpenACCRoutineConstruct( - converter, loc, mod, funcOp, funcName, hasNohost, bindNames, - bindNameDeviceTypes, gangDeviceTypes, gangDimValues, gangDimDeviceTypes, - seqDeviceTypes, workerDeviceTypes, vectorDeviceTypes); + converter, loc, mod, funcOp, funcName, hasNohost, bindIdNames, + bindStrNames, bindIdNameDeviceTypes, bindStrNameDeviceTypes, + gangDeviceTypes, gangDimValues, gangDimDeviceTypes, seqDeviceTypes, + workerDeviceTypes, vectorDeviceTypes); } static void @@ -4822,9 +4888,9 @@ void Fortran::lower::genOpenACCTerminator(fir::FirOpBuilder &builder, mlir::Operation *op, mlir::Location loc) { if (mlir::isa(op)) - builder.create(loc); + mlir::acc::YieldOp::create(builder, loc); else - builder.create(loc); + mlir::acc::TerminatorOp::create(builder, loc); } bool Fortran::lower::isInOpenACCLoop(fir::FirOpBuilder &builder) { @@ -4844,7 +4910,7 @@ void Fortran::lower::genEarlyReturnInOpenACCLoop(fir::FirOpBuilder &builder, mlir::Location loc) { mlir::Value yieldValue = builder.createIntegerConstant(loc, builder.getI1Type(), 1); - builder.create(loc, yieldValue); + mlir::acc::YieldOp::create(builder, loc, yieldValue); } int64_t Fortran::lower::getLoopCountForCollapseAndTile( diff --git a/flang/lib/Lower/OpenMP/Atomic.cpp b/flang/lib/Lower/OpenMP/Atomic.cpp index 6ea331c370640..9a233d2d8cb08 100644 --- a/flang/lib/Lower/OpenMP/Atomic.cpp +++ b/flang/lib/Lower/OpenMP/Atomic.cpp @@ -528,8 +528,8 @@ genAtomicRead(lower::AbstractConverter &converter, }(); builder.restoreInsertionPoint(atomicAt); - mlir::Operation *op = builder.create( - loc, atomAddr, toAddr, mlir::TypeAttr::get(atomType), hint, + mlir::Operation *op = mlir::omp::AtomicReadOp::create( + builder, loc, atomAddr, toAddr, mlir::TypeAttr::get(atomType), hint, makeMemOrderAttr(converter, memOrder)); if (atomType != storeType) { @@ -537,7 +537,7 @@ genAtomicRead(lower::AbstractConverter &converter, // The READ operation could be a part of UPDATE CAPTURE, so make sure // we don't emit extra code into the body of the atomic op. builder.restoreInsertionPoint(postAt); - mlir::Value load = builder.create(loc, toAddr); + mlir::Value load = fir::LoadOp::create(builder, loc, toAddr); overrides.try_emplace(&atom, load); converter.overrideExprValues(&overrides); @@ -545,7 +545,7 @@ genAtomicRead(lower::AbstractConverter &converter, fir::getBase(converter.genExprValue(assign.rhs, stmtCtx, &loc)); converter.resetExprOverrides(); - builder.create(loc, value, storeAddr); + fir::StoreOp::create(builder, loc, value, storeAddr); } return op; } @@ -581,8 +581,9 @@ genAtomicWrite(lower::AbstractConverter &converter, mlir::Value converted = builder.createConvert(loc, atomType, value); builder.restoreInsertionPoint(atomicAt); - mlir::Operation *op = builder.create( - loc, atomAddr, converted, hint, makeMemOrderAttr(converter, memOrder)); + mlir::Operation *op = + mlir::omp::AtomicWriteOp::create(builder, loc, atomAddr, converted, hint, + makeMemOrderAttr(converter, memOrder)); return op; } @@ -635,8 +636,8 @@ genAtomicUpdate(lower::AbstractConverter &converter, } builder.restoreInsertionPoint(atomicAt); - auto updateOp = builder.create( - loc, atomAddr, hint, makeMemOrderAttr(converter, memOrder)); + auto updateOp = mlir::omp::AtomicUpdateOp::create( + builder, loc, atomAddr, hint, makeMemOrderAttr(converter, memOrder)); mlir::Region ®ion = updateOp->getRegion(0); mlir::Block *block = builder.createBlock(®ion, {}, {atomType}, {loc}); @@ -647,7 +648,7 @@ genAtomicUpdate(lower::AbstractConverter &converter, mlir::Value updated = fir::getBase(converter.genExprValue(rhs, stmtCtx, &loc)); mlir::Value converted = builder.createConvert(loc, atomType, updated); - builder.create(loc, converted); + mlir::omp::YieldOp::create(builder, loc, converted); converter.resetExprOverrides(); builder.restoreInsertionPoint(postAt); // For naCtx cleanups @@ -731,8 +732,8 @@ void Fortran::lower::omp::lowerAtomic( "Expexcing two actions"); (void)action0; (void)action1; - captureOp = builder.create( - loc, hint, makeMemOrderAttr(converter, memOrder)); + captureOp = mlir::omp::AtomicCaptureOp::create( + builder, loc, hint, makeMemOrderAttr(converter, memOrder)); // Set the non-atomic insertion point to before the atomic.capture. preAt = getInsertionPointBefore(captureOp); @@ -740,7 +741,7 @@ void Fortran::lower::omp::lowerAtomic( builder.setInsertionPointToEnd(block); // Set the atomic insertion point to before the terminator inside // atomic.capture. - mlir::Operation *term = builder.create(loc); + mlir::Operation *term = mlir::omp::TerminatorOp::create(builder, loc); atomicAt = getInsertionPointBefore(term); postAt = getInsertionPointAfter(captureOp); hint = nullptr; diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp index 74087d42a8e6e..8b3ad57c53810 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp @@ -723,7 +723,7 @@ bool ClauseProcessor::processCopyin() const { // barrier is inserted following all of them. firOpBuilder.restoreInsertionPoint(insPt); if (hasCopyin) - firOpBuilder.create(converter.getCurrentLocation()); + mlir::omp::BarrierOp::create(firOpBuilder, converter.getCurrentLocation()); return hasCopyin; } @@ -803,7 +803,7 @@ createCopyFunc(mlir::Location loc, lower::AbstractConverter &converter, llvm::SmallVector argsTy = {varType, varType}; auto funcType = mlir::FunctionType::get(builder.getContext(), argsTy, {}); mlir::func::FuncOp funcOp = - modBuilder.create(loc, copyFuncName, funcType); + mlir::func::FuncOp::create(modBuilder, loc, copyFuncName, funcType); funcOp.setVisibility(mlir::SymbolTable::Visibility::Private); fir::factory::setInternalLinkage(funcOp); builder.createBlock(&funcOp.getRegion(), funcOp.getRegion().end(), argsTy, @@ -819,22 +819,22 @@ createCopyFunc(mlir::Location loc, lower::AbstractConverter &converter, for (auto extent : typeInfo.getShape()) extents.push_back( builder.createIntegerConstant(loc, builder.getIndexType(), extent)); - shape = builder.create(loc, extents); + shape = fir::ShapeOp::create(builder, loc, extents); } mlir::Value dst = funcOp.getArgument(0); mlir::Value src = funcOp.getArgument(1); llvm::SmallVector typeparams; if (typeInfo.isBoxChar()) { // fir.boxchar will be passed here as fir.ref - auto loadDst = builder.create(loc, dst); - auto loadSrc = builder.create(loc, src); + auto loadDst = fir::LoadOp::create(builder, loc, dst); + auto loadSrc = fir::LoadOp::create(builder, loc, src); // get the actual fir.ref type mlir::Type refType = fir::ReferenceType::get(mlir::cast(eleTy).getEleTy()); - auto unboxedDst = builder.create( - loc, refType, builder.getIndexType(), loadDst); - auto unboxedSrc = builder.create( - loc, refType, builder.getIndexType(), loadSrc); + auto unboxedDst = fir::UnboxCharOp::create(builder, loc, refType, + builder.getIndexType(), loadDst); + auto unboxedSrc = fir::UnboxCharOp::create(builder, loc, refType, + builder.getIndexType(), loadSrc); // Add length to type parameters typeparams.push_back(unboxedDst.getResult(1)); dst = unboxedDst.getResult(0); @@ -844,14 +844,14 @@ createCopyFunc(mlir::Location loc, lower::AbstractConverter &converter, loc, builder.getCharacterLengthType(), *typeInfo.getCharLength()); typeparams.push_back(charLen); } - auto declDst = builder.create( - loc, dst, copyFuncName + "_dst", shape, typeparams, + auto declDst = hlfir::DeclareOp::create( + builder, loc, dst, copyFuncName + "_dst", shape, typeparams, /*dummy_scope=*/nullptr, attrs); - auto declSrc = builder.create( - loc, src, copyFuncName + "_src", shape, typeparams, + auto declSrc = hlfir::DeclareOp::create( + builder, loc, src, copyFuncName + "_src", shape, typeparams, /*dummy_scope=*/nullptr, attrs); converter.copyVar(loc, declDst.getBase(), declSrc.getBase(), varAttrs); - builder.create(loc); + mlir::func::ReturnOp::create(builder, loc); return funcOp; } @@ -882,8 +882,8 @@ bool ClauseProcessor::processCopyprivate( if (mlir::isa(symType) || mlir::isa(symType)) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); - auto alloca = builder.create(currentLocation, symType); - builder.create(currentLocation, symVal, alloca); + auto alloca = fir::AllocaOp::create(builder, currentLocation, symType); + fir::StoreOp::create(builder, currentLocation, symVal, alloca); cpVar = alloca; } @@ -1002,8 +1002,8 @@ bool ClauseProcessor::processDepend(lower::SymMap &symMap, // allocations so this is not a reliable way to identify the dependency. if (auto ref = mlir::dyn_cast(dependVar.getType())) if (fir::isa_box_type(ref.getElementType())) - dependVar = builder.create( - converter.getCurrentLocation(), dependVar); + dependVar = fir::LoadOp::create( + builder, converter.getCurrentLocation(), dependVar); // The openmp dialect doesn't know what to do with boxes (and it would // break layering to teach it about them). The dependency variable can be @@ -1012,8 +1012,8 @@ bool ClauseProcessor::processDepend(lower::SymMap &symMap, // Getting the address of the box data is okay because all the runtime // ultimately cares about is the base address of the array. if (fir::isa_box_type(dependVar.getType())) - dependVar = builder.create( - converter.getCurrentLocation(), dependVar); + dependVar = fir::BoxAddrOp::create( + builder, converter.getCurrentLocation(), dependVar); result.dependVars.push_back(dependVar); } @@ -1315,7 +1315,8 @@ bool ClauseProcessor::processMap( const parser::CharBlock &source) { using Map = omp::clause::Map; mlir::Location clauseLocation = converter.genLocation(source); - const auto &[mapType, typeMods, mappers, iterator, objects] = clause.t; + const auto &[mapType, typeMods, refMod, mappers, iterator, objects] = + clause.t; llvm::omp::OpenMPOffloadMappingFlags mapTypeBits = llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE; std::string mapperIdName = "__implicit_mapper"; @@ -1342,16 +1343,13 @@ bool ClauseProcessor::processMap( mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO | llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM; break; - case Map::MapType::Alloc: - case Map::MapType::Release: + case Map::MapType::Storage: // alloc and release is the default map_type for the Target Data // Ops, i.e. if no bits for map_type is supplied then alloc/release - // is implicitly assumed based on the target directive. Default - // value for Target Data and Enter Data is alloc and for Exit Data - // it is release. + // (aka storage in 6.0+) is implicitly assumed based on the target + // directive. Default value for Target Data and Enter Data is alloc + // and for Exit Data it is release. break; - case Map::MapType::Delete: - mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE; } if (typeMods) { @@ -1362,6 +1360,8 @@ bool ClauseProcessor::processMap( mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT; if (llvm::is_contained(*typeMods, Map::MapTypeModifier::Close)) mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE; + if (llvm::is_contained(*typeMods, Map::MapTypeModifier::Delete)) + mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE; if (llvm::is_contained(*typeMods, Map::MapTypeModifier::OmpxHold)) mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD; } diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp index 22a07219d3a50..686fba0154f44 100644 --- a/flang/lib/Lower/OpenMP/Clauses.cpp +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -1001,19 +1001,21 @@ Map make(const parser::OmpClause::Map &inp, semantics::SemanticsContext &semaCtx) { // inp.v -> parser::OmpMapClause CLAUSET_ENUM_CONVERT( // - convert1, parser::OmpMapType::Value, Map::MapType, + convertMapType, parser::OmpMapType::Value, Map::MapType, // clang-format off - MS(Alloc, Alloc) - MS(Delete, Delete) - MS(From, From) - MS(Release, Release) - MS(To, To) - MS(Tofrom, Tofrom) + MS(Alloc, Storage) + MS(Delete, Storage) + MS(Release, Storage) + MS(Storage, Storage) + MS(From, From) + MS(To, To) + MS(Tofrom, Tofrom) // clang-format on ); CLAUSET_ENUM_CONVERT( // - convert2, parser::OmpMapTypeModifier::Value, Map::MapTypeModifier, + convertMapTypeMod, parser::OmpMapTypeModifier::Value, + Map::MapTypeModifier, // clang-format off MS(Always, Always) MS(Close, Close) @@ -1022,43 +1024,76 @@ Map make(const parser::OmpClause::Map &inp, // clang-format on ); + CLAUSET_ENUM_CONVERT( // + convertRefMod, parser::OmpRefModifier::Value, Map::RefModifier, + // clang-format off + MS(Ref_Ptee, RefPtee) + MS(Ref_Ptr, RefPtr) + MS(Ref_Ptr_Ptee, RefPtrPtee) + // clang-format on + ); + + // Treat always, close, present, self, delete modifiers as map-type- + // modifiers. auto &mods = semantics::OmpGetModifiers(inp.v); - auto *t1 = semantics::OmpGetUniqueModifier(mods); - auto *t2 = semantics::OmpGetUniqueModifier(mods); - auto *t3 = semantics::OmpGetUniqueModifier(mods); - auto &t4 = std::get(inp.v.t); - auto mappers = [&]() -> std::optional> { + auto *t1 = semantics::OmpGetUniqueModifier(mods); + auto &t2 = std::get(inp.v.t); + + auto type = [&]() -> std::optional { if (t1) - return List{Mapper{makeObject(t1->v, semaCtx)}}; + return convertMapType(t1->v); return std::nullopt; }(); - auto iterator = [&]() -> std::optional { - if (t2) - return makeIterator(*t2, semaCtx); + llvm::DenseSet modSet; + if (t1 && t1->v == parser::OmpMapType::Value::Delete) + modSet.insert(Map::MapTypeModifier::Delete); + + for (auto *typeMod : + semantics::OmpGetRepeatableModifier(mods)) { + modSet.insert(convertMapTypeMod(typeMod->v)); + } + if (semantics::OmpGetUniqueModifier(mods)) + modSet.insert(Map::MapTypeModifier::Always); + if (semantics::OmpGetUniqueModifier(mods)) + modSet.insert(Map::MapTypeModifier::Close); + if (semantics::OmpGetUniqueModifier(mods)) + modSet.insert(Map::MapTypeModifier::Delete); + if (semantics::OmpGetUniqueModifier(mods)) + modSet.insert(Map::MapTypeModifier::Present); + if (semantics::OmpGetUniqueModifier(mods)) + modSet.insert(Map::MapTypeModifier::Self); + if (semantics::OmpGetUniqueModifier(mods)) + modSet.insert(Map::MapTypeModifier::OmpxHold); + + std::optional maybeTypeMods{}; + if (!modSet.empty()) + maybeTypeMods = Map::MapTypeModifiers(modSet.begin(), modSet.end()); + + auto refMod = [&]() -> std::optional { + if (auto *t = semantics::OmpGetUniqueModifier(mods)) + return convertRefMod(t->v); return std::nullopt; }(); - auto type = [&]() -> std::optional { - if (t3) - return convert1(t3->v); + auto mappers = [&]() -> std::optional> { + if (auto *t = semantics::OmpGetUniqueModifier(mods)) + return List{Mapper{makeObject(t->v, semaCtx)}}; return std::nullopt; }(); - Map::MapTypeModifiers typeMods; - for (auto *typeMod : - semantics::OmpGetRepeatableModifier(mods)) { - typeMods.push_back(convert2(typeMod->v)); - } - std::optional maybeTypeMods{}; - if (!typeMods.empty()) - maybeTypeMods = std::move(typeMods); + auto iterator = [&]() -> std::optional { + if (auto *t = semantics::OmpGetUniqueModifier(mods)) + return makeIterator(*t, semaCtx); + return std::nullopt; + }(); return Map{{/*MapType=*/std::move(type), /*MapTypeModifiers=*/std::move(maybeTypeMods), - /*Mapper=*/std::move(mappers), /*Iterator=*/std::move(iterator), - /*LocatorList=*/makeObjects(t4, semaCtx)}}; + /*RefModifier=*/std::move(refMod), /*Mapper=*/std::move(mappers), + /*Iterator=*/std::move(iterator), + /*LocatorList=*/makeObjects(t2, semaCtx)}}; } Match make(const parser::OmpClause::Match &inp, diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp index 3fae3f3a0ddfd..11e488371b886 100644 --- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp +++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp @@ -26,6 +26,8 @@ #include "flang/Optimizer/HLFIR/HLFIROps.h" #include "flang/Semantics/attr.h" #include "flang/Semantics/tools.h" +#include "llvm/ADT/Sequence.h" +#include "llvm/ADT/SmallSet.h" namespace Fortran { namespace lower { @@ -49,7 +51,7 @@ DataSharingProcessor::DataSharingProcessor( firOpBuilder(converter.getFirOpBuilder()), clauses(clauses), eval(eval), shouldCollectPreDeterminedSymbols(shouldCollectPreDeterminedSymbols), useDelayedPrivatization(useDelayedPrivatization), symTable(symTable), - visitor() { + visitor(semaCtx) { eval.visit([&](const auto &functionParserNode) { parser::Walk(functionParserNode, visitor); }); @@ -289,7 +291,7 @@ void DataSharingProcessor::insertBarrier( clauseOps->privateNeedsBarrier = mlir::UnitAttr::get(&converter.getMLIRContext()); } else { - firOpBuilder.create(converter.getCurrentLocation()); + mlir::omp::BarrierOp::create(firOpBuilder, converter.getCurrentLocation()); } } @@ -349,32 +351,32 @@ void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) { loopOp.getIVs(), result.loopUpperBounds, result.loopSteps)) { // v = iv + step // cmp = step < 0 ? v < ub : v > ub - mlir::Value v = firOpBuilder.create(loc, iv, step); + mlir::Value v = mlir::arith::AddIOp::create(firOpBuilder, loc, iv, step); vs.push_back(v); mlir::Value zero = firOpBuilder.createIntegerConstant(loc, step.getType(), 0); - mlir::Value negativeStep = firOpBuilder.create( - loc, mlir::arith::CmpIPredicate::slt, step, zero); - mlir::Value vLT = firOpBuilder.create( - loc, mlir::arith::CmpIPredicate::slt, v, ub); - mlir::Value vGT = firOpBuilder.create( - loc, mlir::arith::CmpIPredicate::sgt, v, ub); - mlir::Value icmpOp = firOpBuilder.create( - loc, negativeStep, vLT, vGT); + mlir::Value negativeStep = mlir::arith::CmpIOp::create( + firOpBuilder, loc, mlir::arith::CmpIPredicate::slt, step, zero); + mlir::Value vLT = mlir::arith::CmpIOp::create( + firOpBuilder, loc, mlir::arith::CmpIPredicate::slt, v, ub); + mlir::Value vGT = mlir::arith::CmpIOp::create( + firOpBuilder, loc, mlir::arith::CmpIPredicate::sgt, v, ub); + mlir::Value icmpOp = mlir::arith::SelectOp::create( + firOpBuilder, loc, negativeStep, vLT, vGT); if (cmpOp) - cmpOp = firOpBuilder.create(loc, cmpOp, icmpOp); + cmpOp = mlir::arith::AndIOp::create(firOpBuilder, loc, cmpOp, icmpOp); else cmpOp = icmpOp; } - auto ifOp = firOpBuilder.create(loc, cmpOp, /*else*/ false); + auto ifOp = fir::IfOp::create(firOpBuilder, loc, cmpOp, /*else*/ false); firOpBuilder.setInsertionPointToStart(&ifOp.getThenRegion().front()); for (auto [v, loopIV] : llvm::zip_equal(vs, loopIVs)) { hlfir::Entity loopIVEntity{loopIV}; loopIVEntity = hlfir::derefPointersAndAllocatables(loc, firOpBuilder, loopIVEntity); - firOpBuilder.create(loc, v, loopIVEntity); + hlfir::AssignOp::create(firOpBuilder, loc, v, loopIVEntity); } lastPrivIP = firOpBuilder.saveInsertionPoint(); } else if (mlir::isa(op)) { @@ -424,24 +426,55 @@ getSource(const semantics::SemanticsContext &semaCtx, return source; } +static void collectPrivatizingConstructs( + llvm::SmallSet &constructs, unsigned version) { + using Clause = llvm::omp::Clause; + using Directive = llvm::omp::Directive; + + static const Clause privatizingClauses[] = { + Clause::OMPC_private, + Clause::OMPC_lastprivate, + Clause::OMPC_firstprivate, + Clause::OMPC_in_reduction, + Clause::OMPC_reduction, + Clause::OMPC_linear, + // TODO: Clause::OMPC_induction, + Clause::OMPC_task_reduction, + Clause::OMPC_detach, + Clause::OMPC_use_device_ptr, + Clause::OMPC_is_device_ptr, + }; + + for (auto dir : llvm::enum_seq_inclusive(Directive::First_, + Directive::Last_)) { + bool allowsPrivatizing = llvm::any_of(privatizingClauses, [&](Clause cls) { + return llvm::omp::isAllowedClauseForDirective(dir, cls, version); + }); + if (allowsPrivatizing) + constructs.insert(dir); + } +} + bool DataSharingProcessor::isOpenMPPrivatizingConstruct( - const parser::OpenMPConstruct &omp) { - return common::visit( - [](auto &&s) { - using BareS = llvm::remove_cvref_t; - return std::is_same_v || - std::is_same_v || - std::is_same_v; - }, - omp.u); + const parser::OpenMPConstruct &omp, unsigned version) { + static llvm::SmallSet privatizing; + [[maybe_unused]] static bool init = + (collectPrivatizingConstructs(privatizing, version), true); + + // As of OpenMP 6.0, privatizing constructs (with the test being if they + // allow a privatizing clause) are: dispatch, distribute, do, for, loop, + // parallel, scope, sections, simd, single, target, target_data, task, + // taskgroup, taskloop, and teams. + return llvm::is_contained(privatizing, extractOmpDirective(omp)); } bool DataSharingProcessor::isOpenMPPrivatizingEvaluation( const pft::Evaluation &eval) const { - return eval.visit([](auto &&s) { + unsigned version = semaCtx.langOptions().OpenMPVersion; + return eval.visit([=](auto &&s) { using BareS = llvm::remove_cvref_t; if constexpr (std::is_same_v) { - return isOpenMPPrivatizingConstruct(s); + return isOpenMPPrivatizingConstruct(s, version); } else { return false; } diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.h b/flang/lib/Lower/OpenMP/DataSharingProcessor.h index ee2fc70d2e673..bc422f410403a 100644 --- a/flang/lib/Lower/OpenMP/DataSharingProcessor.h +++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.h @@ -36,6 +36,8 @@ class DataSharingProcessor { /// at any point in time. This is used to track Symbol definition scopes in /// order to tell which OMP scope defined vs. references a certain Symbol. struct OMPConstructSymbolVisitor { + OMPConstructSymbolVisitor(semantics::SemanticsContext &ctx) + : version(ctx.langOptions().OpenMPVersion) {} template bool Pre(const T &) { return true; @@ -45,13 +47,13 @@ class DataSharingProcessor { bool Pre(const parser::OpenMPConstruct &omp) { // Skip constructs that may not have privatizations. - if (isOpenMPPrivatizingConstruct(omp)) + if (isOpenMPPrivatizingConstruct(omp, version)) constructs.push_back(&omp); return true; } void Post(const parser::OpenMPConstruct &omp) { - if (isOpenMPPrivatizingConstruct(omp)) + if (isOpenMPPrivatizingConstruct(omp, version)) constructs.pop_back(); } @@ -68,6 +70,9 @@ class DataSharingProcessor { /// construct that defines symbol. bool isSymbolDefineBy(const semantics::Symbol *symbol, lower::pft::Evaluation &eval) const; + + private: + unsigned version; }; mlir::OpBuilder::InsertPoint lastPrivIP; @@ -115,7 +120,8 @@ class DataSharingProcessor { mlir::OpBuilder::InsertPoint *lastPrivIP); void insertDeallocs(); - static bool isOpenMPPrivatizingConstruct(const parser::OpenMPConstruct &omp); + static bool isOpenMPPrivatizingConstruct(const parser::OpenMPConstruct &omp, + unsigned version); bool isOpenMPPrivatizingEvaluation(const pft::Evaluation &eval) const; public: diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 4458f62eea95a..fc5fef9b2c577 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -63,6 +63,28 @@ static void processHostEvalClauses(lower::AbstractConverter &converter, lower::pft::Evaluation &eval, mlir::Location loc); +static llvm::omp::Directive +getOpenMPDirectiveEnum(const parser::OmpLoopDirective &beginStatment) { + return beginStatment.v; +} + +static llvm::omp::Directive getOpenMPDirectiveEnum( + const parser::OmpBeginLoopDirective &beginLoopDirective) { + return getOpenMPDirectiveEnum( + std::get(beginLoopDirective.t)); +} + +static llvm::omp::Directive +getOpenMPDirectiveEnum(const parser::OpenMPLoopConstruct &ompLoopConstruct) { + return getOpenMPDirectiveEnum( + std::get(ompLoopConstruct.t)); +} + +static llvm::omp::Directive getOpenMPDirectiveEnum( + const common::Indirection &ompLoopConstruct) { + return getOpenMPDirectiveEnum(ompLoopConstruct.value()); +} + namespace { /// Structure holding information that is needed to pass host-evaluated /// information to later lowering stages. @@ -372,90 +394,6 @@ extractMappedBaseValues(llvm::ArrayRef vars, }); } -/// Get the directive enumeration value corresponding to the given OpenMP -/// construct PFT node. -llvm::omp::Directive -extractOmpDirective(const parser::OpenMPConstruct &ompConstruct) { - return common::visit( - common::visitors{ - [](const parser::OpenMPAllocatorsConstruct &c) { - return llvm::omp::OMPD_allocators; - }, - [](const parser::OpenMPAssumeConstruct &c) { - return llvm::omp::OMPD_assume; - }, - [](const parser::OpenMPAtomicConstruct &c) { - return llvm::omp::OMPD_atomic; - }, - [](const parser::OpenMPBlockConstruct &c) { - return std::get( - std::get(c.t).t) - .v; - }, - [](const parser::OpenMPCriticalConstruct &c) { - return llvm::omp::OMPD_critical; - }, - [](const parser::OpenMPDeclarativeAllocate &c) { - return llvm::omp::OMPD_allocate; - }, - [](const parser::OpenMPDispatchConstruct &c) { - return llvm::omp::OMPD_dispatch; - }, - [](const parser::OpenMPExecutableAllocate &c) { - return llvm::omp::OMPD_allocate; - }, - [](const parser::OpenMPLoopConstruct &c) { - return std::get( - std::get(c.t).t) - .v; - }, - [](const parser::OpenMPSectionConstruct &c) { - return llvm::omp::OMPD_section; - }, - [](const parser::OpenMPSectionsConstruct &c) { - return std::get( - std::get(c.t).t) - .v; - }, - [](const parser::OpenMPStandaloneConstruct &c) { - return common::visit( - common::visitors{ - [](const parser::OpenMPSimpleStandaloneConstruct &c) { - return c.v.DirId(); - }, - [](const parser::OpenMPFlushConstruct &c) { - return llvm::omp::OMPD_flush; - }, - [](const parser::OpenMPCancelConstruct &c) { - return llvm::omp::OMPD_cancel; - }, - [](const parser::OpenMPCancellationPointConstruct &c) { - return llvm::omp::OMPD_cancellation_point; - }, - [](const parser::OmpMetadirectiveDirective &c) { - return llvm::omp::OMPD_metadirective; - }, - [](const parser::OpenMPDepobjConstruct &c) { - return llvm::omp::OMPD_depobj; - }, - [](const parser::OpenMPInteropConstruct &c) { - return llvm::omp::OMPD_interop; - }}, - c.u); - }, - [](const parser::OpenMPUtilityConstruct &c) { - return common::visit( - common::visitors{[](const parser::OmpErrorDirective &c) { - return llvm::omp::OMPD_error; - }, - [](const parser::OmpNothingDirective &c) { - return llvm::omp::OMPD_nothing; - }}, - c.u); - }}, - ompConstruct.u); -} - /// Populate the global \see hostEvalInfo after processing clauses for the given /// \p eval OpenMP target construct, or nested constructs, if these must be /// evaluated outside of the target region per the spec. @@ -726,8 +664,8 @@ static void threadPrivatizeVars(lower::AbstractConverter &converter, op = declOp.getMemref().getDefiningOp(); if (mlir::isa(op)) symValue = mlir::dyn_cast(op).getSymAddr(); - return firOpBuilder.create( - currentLocation, symValue.getType(), symValue); + return mlir::omp::ThreadprivateOp::create(firOpBuilder, currentLocation, + symValue.getType(), symValue); }; llvm::SetVector threadprivateSyms; @@ -794,7 +732,7 @@ createAndSetPrivatizedLoopVar(lower::AbstractConverter &converter, lhs = hlfir::derefPointersAndAllocatables(loc, firOpBuilder, lhs); mlir::Operation *storeOp = - firOpBuilder.create(loc, cvtVal, lhs); + hlfir::AssignOp::create(firOpBuilder, loc, cvtVal, lhs); return storeOp; } @@ -1240,8 +1178,8 @@ static void createBodyOfOp(mlir::Operation &op, const OpWithBodyGenInfo &info, fir::FirOpBuilder &firOpBuilder = info.converter.getFirOpBuilder(); auto insertMarker = [](fir::FirOpBuilder &builder) { - mlir::Value undef = builder.create(builder.getUnknownLoc(), - builder.getIndexType()); + mlir::Value undef = fir::UndefOp::create(builder, builder.getUnknownLoc(), + builder.getIndexType()); return undef.getDefiningOp(); }; @@ -1355,7 +1293,7 @@ static void createBodyOfOp(mlir::Operation &op, const OpWithBodyGenInfo &info, mlir::Block *exit = firOpBuilder.createBlock(®ion); for (mlir::Block *b : exits) { firOpBuilder.setInsertionPointToEnd(b); - firOpBuilder.create(info.loc, exit); + mlir::cf::BranchOp::create(firOpBuilder, info.loc, exit); } return exit; }; @@ -1416,8 +1354,8 @@ static void genBodyOfTargetDataOp( // Remembering the position for further insertion is important since // there are hlfir.declares inserted above while setting block arguments // and new code from the body should be inserted after that. - mlir::Value undefMarker = firOpBuilder.create( - dataOp.getLoc(), firOpBuilder.getIndexType()); + mlir::Value undefMarker = fir::UndefOp::create(firOpBuilder, dataOp.getLoc(), + firOpBuilder.getIndexType()); // Create blocks for unstructured regions. This has to be done since // blocks are initially allocated with the function as the parent region. @@ -1426,7 +1364,7 @@ static void genBodyOfTargetDataOp( firOpBuilder, eval.getNestedEvaluations()); } - firOpBuilder.create(currentLocation); + mlir::omp::TerminatorOp::create(firOpBuilder, currentLocation); // Set the insertion point after the marker. firOpBuilder.setInsertionPointAfter(undefMarker.getDefiningOp()); @@ -1580,8 +1518,8 @@ static void genBodyOfTargetOp( insertIndex, copyVal.getType(), copyVal.getLoc()); firOpBuilder.setInsertionPointToStart(entryBlock); - auto loadOp = firOpBuilder.create(clonedValArg.getLoc(), - clonedValArg); + auto loadOp = fir::LoadOp::create(firOpBuilder, clonedValArg.getLoc(), + clonedValArg); val.replaceUsesWithIf(loadOp->getResult(0), [entryBlock](mlir::OpOperand &use) { return use.getOwner()->getBlock() == entryBlock; @@ -1597,8 +1535,8 @@ static void genBodyOfTargetOp( // marker will be deleted since there are not uses. // In the HLFIR flow there are hlfir.declares inserted above while // setting block arguments. - mlir::Value undefMarker = firOpBuilder.create( - targetOp.getLoc(), firOpBuilder.getIndexType()); + mlir::Value undefMarker = fir::UndefOp::create( + firOpBuilder, targetOp.getLoc(), firOpBuilder.getIndexType()); // Create blocks for unstructured regions. This has to be done since // blocks are initially allocated with the function as the parent region. @@ -1608,7 +1546,7 @@ static void genBodyOfTargetOp( firOpBuilder, eval.getNestedEvaluations()); } - firOpBuilder.create(currentLocation); + mlir::omp::TerminatorOp::create(firOpBuilder, currentLocation); // Create the insertion point after the marker. firOpBuilder.setInsertionPointAfter(undefMarker.getDefiningOp()); @@ -1654,7 +1592,7 @@ static OpTy genWrapperOp(lower::AbstractConverter &converter, fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); // Create wrapper. - auto op = firOpBuilder.create(loc, clauseOps); + auto op = OpTy::create(firOpBuilder, loc, clauseOps); // Create entry block with arguments. genEntryBlock(firOpBuilder, args, op.getRegion()); @@ -2067,7 +2005,7 @@ genCriticalOp(lower::AbstractConverter &converter, lower::SymMap &symTable, clauseOps, nameStr); mlir::OpBuilder modBuilder(mod.getBodyRegion()); - global = modBuilder.create(loc, clauseOps); + global = mlir::omp::CriticalDeclareOp::create(modBuilder, loc, clauseOps); } nameAttr = mlir::FlatSymbolRefAttr::get(firOpBuilder.getContext(), global.getSymName()); @@ -2153,6 +2091,163 @@ genLoopOp(lower::AbstractConverter &converter, lower::SymMap &symTable, return loopOp; } +static mlir::omp::CanonicalLoopOp +genCanonicalLoopOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, mlir::Location loc, + const ConstructQueue &queue, + ConstructQueue::const_iterator item, + llvm::ArrayRef ivs, + llvm::omp::Directive directive, DataSharingProcessor &dsp) { + fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); + + assert(ivs.size() == 1 && "Nested loops not yet implemented"); + const semantics::Symbol *iv = ivs[0]; + + auto &nestedEval = eval.getFirstNestedEvaluation(); + if (nestedEval.getIf()->IsDoConcurrent()) { + // OpenMP specifies DO CONCURRENT only with the `!omp loop` construct. Will + // need to add special cases for this combination. + TODO(loc, "DO CONCURRENT as canonical loop not supported"); + } + + // Get the loop bounds (and increment) + auto &doLoopEval = nestedEval.getFirstNestedEvaluation(); + auto *doStmt = doLoopEval.getIf(); + assert(doStmt && "Expected do loop to be in the nested evaluation"); + auto &loopControl = std::get>(doStmt->t); + assert(loopControl.has_value()); + auto *bounds = std::get_if(&loopControl->u); + assert(bounds && "Expected bounds for canonical loop"); + lower::StatementContext stmtCtx; + mlir::Value loopLBVar = fir::getBase( + converter.genExprValue(*semantics::GetExpr(bounds->lower), stmtCtx)); + mlir::Value loopUBVar = fir::getBase( + converter.genExprValue(*semantics::GetExpr(bounds->upper), stmtCtx)); + mlir::Value loopStepVar = [&]() { + if (bounds->step) { + return fir::getBase( + converter.genExprValue(*semantics::GetExpr(bounds->step), stmtCtx)); + } + + // If `step` is not present, assume it is `1`. + return firOpBuilder.createIntegerConstant(loc, firOpBuilder.getI32Type(), + 1); + }(); + + // Get the integer kind for the loop variable and cast the loop bounds + size_t loopVarTypeSize = bounds->name.thing.symbol->GetUltimate().size(); + mlir::Type loopVarType = getLoopVarType(converter, loopVarTypeSize); + loopLBVar = firOpBuilder.createConvert(loc, loopVarType, loopLBVar); + loopUBVar = firOpBuilder.createConvert(loc, loopVarType, loopUBVar); + loopStepVar = firOpBuilder.createConvert(loc, loopVarType, loopStepVar); + + // Start lowering + mlir::Value zero = firOpBuilder.createIntegerConstant(loc, loopVarType, 0); + mlir::Value one = firOpBuilder.createIntegerConstant(loc, loopVarType, 1); + mlir::Value isDownwards = firOpBuilder.create( + loc, mlir::arith::CmpIPredicate::slt, loopStepVar, zero); + + // Ensure we are counting upwards. If not, negate step and swap lb and ub. + mlir::Value negStep = + firOpBuilder.create(loc, zero, loopStepVar); + mlir::Value incr = firOpBuilder.create( + loc, isDownwards, negStep, loopStepVar); + mlir::Value lb = firOpBuilder.create( + loc, isDownwards, loopUBVar, loopLBVar); + mlir::Value ub = firOpBuilder.create( + loc, isDownwards, loopLBVar, loopUBVar); + + // Compute the trip count assuming lb <= ub. This guarantees that the result + // is non-negative and we can use unsigned arithmetic. + mlir::Value span = firOpBuilder.create( + loc, ub, lb, ::mlir::arith::IntegerOverflowFlags::nuw); + mlir::Value tcMinusOne = + firOpBuilder.create(loc, span, incr); + mlir::Value tcIfLooping = firOpBuilder.create( + loc, tcMinusOne, one, ::mlir::arith::IntegerOverflowFlags::nuw); + + // Fall back to 0 if lb > ub + mlir::Value isZeroTC = firOpBuilder.create( + loc, mlir::arith::CmpIPredicate::slt, ub, lb); + mlir::Value tripcount = firOpBuilder.create( + loc, isZeroTC, zero, tcIfLooping); + + // Create the CLI handle. + auto newcli = firOpBuilder.create(loc); + mlir::Value cli = newcli.getResult(); + + auto ivCallback = [&](mlir::Operation *op) + -> llvm::SmallVector { + mlir::Region ®ion = op->getRegion(0); + + // Create the op's region skeleton (BB taking the iv as argument) + firOpBuilder.createBlock(®ion, {}, {loopVarType}, {loc}); + + // Compute the value of the loop variable from the logical iteration number. + mlir::Value natIterNum = fir::getBase(region.front().getArgument(0)); + mlir::Value scaled = + firOpBuilder.create(loc, natIterNum, loopStepVar); + mlir::Value userVal = + firOpBuilder.create(loc, loopLBVar, scaled); + + // The argument is not currently in memory, so make a temporary for the + // argument, and store it there, then bind that location to the argument. + mlir::Operation *storeOp = + createAndSetPrivatizedLoopVar(converter, loc, userVal, iv); + + firOpBuilder.setInsertionPointAfter(storeOp); + return {iv}; + }; + + // Create the omp.canonical_loop operation + auto canonLoop = genOpWithBody( + OpWithBodyGenInfo(converter, symTable, semaCtx, loc, nestedEval, + directive) + .setClauses(&item->clauses) + .setDataSharingProcessor(&dsp) + .setGenRegionEntryCb(ivCallback), + queue, item, tripcount, cli); + + firOpBuilder.setInsertionPointAfter(canonLoop); + return canonLoop; +} + +static void genUnrollOp(Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symTable, + lower::StatementContext &stmtCtx, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + mlir::Location loc, const ConstructQueue &queue, + ConstructQueue::const_iterator item) { + fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); + + mlir::omp::LoopRelatedClauseOps loopInfo; + llvm::SmallVector iv; + collectLoopRelatedInfo(converter, loc, eval, item->clauses, loopInfo, iv); + + // Clauses for unrolling not yet implemnted + ClauseProcessor cp(converter, semaCtx, item->clauses); + cp.processTODO( + loc, llvm::omp::Directive::OMPD_unroll); + + // Even though unroll does not support data-sharing clauses, but this is + // required to fill the symbol table. + DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval, + /*shouldCollectPreDeterminedSymbols=*/true, + /*useDelayedPrivatization=*/false, symTable); + dsp.processStep1(); + + // Emit the associated loop + auto canonLoop = + genCanonicalLoopOp(converter, symTable, semaCtx, eval, loc, queue, item, + iv, llvm::omp::Directive::OMPD_unroll, dsp); + + // Apply unrolling to it + auto cli = canonLoop.getCli(); + firOpBuilder.create(loc, cli); +} + static mlir::omp::MaskedOp genMaskedOp(lower::AbstractConverter &converter, lower::SymMap &symTable, lower::StatementContext &stmtCtx, @@ -2285,7 +2380,7 @@ genSectionsOp(lower::AbstractConverter &converter, lower::SymMap &symTable, } // SECTIONS construct. - auto sectionsOp = builder.create(loc, clauseOps); + auto sectionsOp = mlir::omp::SectionsOp::create(builder, loc, clauseOps); // Create entry block with reduction variables as arguments. EntryBlockArgs args; @@ -2361,7 +2456,7 @@ genSectionsOp(lower::AbstractConverter &converter, lower::SymMap &symTable, // races on post-update of lastprivate variables when `nowait` // clause is present. if (clauseOps.nowait && !lastprivates.empty()) - builder.create(loc); + mlir::omp::BarrierOp::create(builder, loc); return sectionsOp; } @@ -2513,7 +2608,7 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable, }; lower::pft::visitAllSymbols(eval, captureImplicitMap); - auto targetOp = firOpBuilder.create(loc, clauseOps); + auto targetOp = mlir::omp::TargetOp::create(firOpBuilder, loc, clauseOps); llvm::SmallVector hasDeviceAddrBaseValues, mapBaseValues; extractMappedBaseValues(clauseOps.hasDeviceAddrVars, hasDeviceAddrBaseValues); @@ -2593,7 +2688,7 @@ static OpTy genTargetEnterExitUpdateDataOp( genTargetEnterExitUpdateDataClauses(converter, semaCtx, symTable, stmtCtx, item->clauses, loc, directive, clauseOps); - return firOpBuilder.create(loc, clauseOps); + return OpTy::create(firOpBuilder, loc, clauseOps); } static mlir::omp::TaskOp @@ -3333,12 +3428,14 @@ static void genOMPDispatch(lower::AbstractConverter &converter, newOp = genTeamsOp(converter, symTable, stmtCtx, semaCtx, eval, loc, queue, item); break; - case llvm::omp::Directive::OMPD_tile: - case llvm::omp::Directive::OMPD_unroll: { + case llvm::omp::Directive::OMPD_tile: { unsigned version = semaCtx.langOptions().OpenMPVersion; TODO(loc, "Unhandled loop directive (" + llvm::omp::getOpenMPDirectiveName(dir, version) + ")"); } + case llvm::omp::Directive::OMPD_unroll: + genUnrollOp(converter, symTable, stmtCtx, semaCtx, eval, loc, queue, item); + break; // case llvm::omp::Directive::OMPD_workdistribute: case llvm::omp::Directive::OMPD_workshare: newOp = genWorkshareOp(converter, symTable, stmtCtx, semaCtx, eval, loc, @@ -3426,8 +3523,8 @@ genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, firOpBuilder.setInsertionPointToStart(converter.getModuleOp().getBody()); auto mlirType = converter.genType(varType.declTypeSpec->derivedTypeSpec()); - auto declMapperOp = firOpBuilder.create( - loc, mapperNameStr, mlirType); + auto declMapperOp = mlir::omp::DeclareMapperOp::create( + firOpBuilder, loc, mapperNameStr, mlirType); auto ®ion = declMapperOp.getRegion(); firOpBuilder.createBlock(®ion); auto varVal = region.addArgument(firOpBuilder.getRefType(mlirType), loc); @@ -3440,7 +3537,7 @@ genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, List clauses = makeClauses(*clauseList, semaCtx); ClauseProcessor cp(converter, semaCtx, clauses); cp.processMap(loc, stmtCtx, clauseOps); - firOpBuilder.create(loc, clauseOps.mapVars); + mlir::omp::DeclareMapperInfoOp::create(firOpBuilder, loc, clauseOps.mapVars); } static void @@ -3774,12 +3871,25 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, if (auto *ompNestedLoopCons{ std::get_if>( &*optLoopCons)}) { - genOMP(converter, symTable, semaCtx, eval, ompNestedLoopCons->value()); + llvm::omp::Directive nestedDirective = + getOpenMPDirectiveEnum(*ompNestedLoopCons); + switch (nestedDirective) { + case llvm::omp::Directive::OMPD_tile: + // Emit the omp.loop_nest with annotation for tiling + genOMP(converter, symTable, semaCtx, eval, ompNestedLoopCons->value()); + break; + default: { + unsigned version = semaCtx.langOptions().OpenMPVersion; + TODO(currentLocation, + "Applying a loop-associated on the loop generated by the " + + llvm::omp::getOpenMPDirectiveName(nestedDirective, version) + + " construct"); + } + } } } - llvm::omp::Directive directive = - std::get(beginLoopDirective.t).v; + llvm::omp::Directive directive = getOpenMPDirectiveEnum(beginLoopDirective); const parser::CharBlock &source = std::get(beginLoopDirective.t).source; ConstructQueue queue{ @@ -3842,8 +3952,8 @@ mlir::Operation *Fortran::lower::genOpenMPTerminator(fir::FirOpBuilder &builder, mlir::Location loc) { if (mlir::isa(op)) - return builder.create(loc); - return builder.create(loc); + return mlir::omp::YieldOp::create(builder, loc); + return mlir::omp::TerminatorOp::create(builder, loc); } void Fortran::lower::genOpenMPConstruct(lower::AbstractConverter &converter, @@ -3903,9 +4013,8 @@ void Fortran::lower::genThreadprivateOp(lower::AbstractConverter &converter, return; } // Generate ThreadprivateOp and rebind the common block. - mlir::Value commonThreadprivateValue = - firOpBuilder.create( - currentLocation, commonValue.getType(), commonValue); + mlir::Value commonThreadprivateValue = mlir::omp::ThreadprivateOp::create( + firOpBuilder, currentLocation, commonValue.getType(), commonValue); converter.bindSymbol(*common, commonThreadprivateValue); // Generate the threadprivate value for the common block member. symThreadprivateValue = genCommonBlockMember(converter, currentLocation, @@ -3925,10 +4034,10 @@ void Fortran::lower::genThreadprivateOp(lower::AbstractConverter &converter, global = globalInitialization(converter, firOpBuilder, sym, var, currentLocation); - mlir::Value symValue = firOpBuilder.create( - currentLocation, global.resultType(), global.getSymbol()); - symThreadprivateValue = firOpBuilder.create( - currentLocation, symValue.getType(), symValue); + mlir::Value symValue = fir::AddrOfOp::create( + firOpBuilder, currentLocation, global.resultType(), global.getSymbol()); + symThreadprivateValue = mlir::omp::ThreadprivateOp::create( + firOpBuilder, currentLocation, symValue.getType(), symValue); } else { mlir::Value symValue = converter.getSymbolAddress(sym); @@ -3943,8 +4052,8 @@ void Fortran::lower::genThreadprivateOp(lower::AbstractConverter &converter, if (mlir::isa(op)) return; - symThreadprivateValue = firOpBuilder.create( - currentLocation, symValue.getType(), symValue); + symThreadprivateValue = mlir::omp::ThreadprivateOp::create( + firOpBuilder, currentLocation, symValue.getType(), symValue); } fir::ExtendedValue sexv = converter.getSymbolExtendedValue(sym); diff --git a/flang/lib/Lower/OpenMP/Utils.cpp b/flang/lib/Lower/OpenMP/Utils.cpp index 2e53f01f1da6a..b1716d6afb200 100644 --- a/flang/lib/Lower/OpenMP/Utils.cpp +++ b/flang/lib/Lower/OpenMP/Utils.cpp @@ -115,7 +115,7 @@ createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc, mlir::omp::VariableCaptureKind mapCaptureType, mlir::Type retTy, bool partialMap, mlir::FlatSymbolRefAttr mapperId) { if (auto boxTy = llvm::dyn_cast(baseAddr.getType())) { - baseAddr = builder.create(loc, baseAddr); + baseAddr = fir::BoxAddrOp::create(builder, loc, baseAddr); retTy = baseAddr.getType(); } @@ -129,8 +129,8 @@ createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc, if (seqType.hasDynamicExtents()) varType = mlir::TypeAttr::get(seqType.getEleTy()); - mlir::omp::MapInfoOp op = builder.create( - loc, retTy, baseAddr, varType, + mlir::omp::MapInfoOp op = mlir::omp::MapInfoOp::create( + builder, loc, retTy, baseAddr, varType, builder.getIntegerAttr(builder.getIntegerType(64, false), mapType), builder.getAttr(mapCaptureType), varPtrPtr, members, membersIndex, bounds, mapperId, @@ -195,8 +195,8 @@ static void generateArrayIndices(lower::AbstractConverter &converter, clauseLocation, firOpBuilder.getIndexType(), 1); subscript = firOpBuilder.createConvert( clauseLocation, firOpBuilder.getIndexType(), subscript); - indices.push_back(firOpBuilder.create(clauseLocation, - subscript, one)); + indices.push_back(mlir::arith::SubIOp::create(firOpBuilder, clauseLocation, + subscript, one)); } } @@ -329,9 +329,10 @@ mlir::Value createParentSymAndGenIntermediateMaps( subscriptIndices, objectList[i]); assert(!subscriptIndices.empty() && "missing expected indices for map clause"); - curValue = firOpBuilder.create( - clauseLocation, firOpBuilder.getRefType(arrType.getEleTy()), - curValue, subscriptIndices); + curValue = fir::CoordinateOp::create( + firOpBuilder, clauseLocation, + firOpBuilder.getRefType(arrType.getEleTy()), curValue, + subscriptIndices); } } @@ -345,9 +346,9 @@ mlir::Value createParentSymAndGenIntermediateMaps( fir::IntOrValue idxConst = mlir::IntegerAttr::get( firOpBuilder.getI32Type(), indices[currentIndicesIdx]); mlir::Type memberTy = recordType.getType(indices[currentIndicesIdx]); - curValue = firOpBuilder.create( - clauseLocation, firOpBuilder.getRefType(memberTy), curValue, - llvm::SmallVector{idxConst}); + curValue = fir::CoordinateOp::create( + firOpBuilder, clauseLocation, firOpBuilder.getRefType(memberTy), + curValue, llvm::SmallVector{idxConst}); // If we're a final member, the map will be generated by the processMap // call that invoked this function. @@ -417,7 +418,7 @@ mlir::Value createParentSymAndGenIntermediateMaps( // Load the currently accessed member, so we can continue to access // further segments. - curValue = firOpBuilder.create(clauseLocation, curValue); + curValue = fir::LoadOp::create(firOpBuilder, clauseLocation, curValue); currentIndicesIdx++; } } @@ -661,6 +662,90 @@ bool collectLoopRelatedInfo( return found; } + +/// Get the directive enumeration value corresponding to the given OpenMP +/// construct PFT node. +llvm::omp::Directive +extractOmpDirective(const parser::OpenMPConstruct &ompConstruct) { + return common::visit( + common::visitors{ + [](const parser::OpenMPAllocatorsConstruct &c) { + return llvm::omp::OMPD_allocators; + }, + [](const parser::OpenMPAssumeConstruct &c) { + return llvm::omp::OMPD_assume; + }, + [](const parser::OpenMPAtomicConstruct &c) { + return llvm::omp::OMPD_atomic; + }, + [](const parser::OpenMPBlockConstruct &c) { + return std::get( + std::get(c.t).t) + .v; + }, + [](const parser::OpenMPCriticalConstruct &c) { + return llvm::omp::OMPD_critical; + }, + [](const parser::OpenMPDeclarativeAllocate &c) { + return llvm::omp::OMPD_allocate; + }, + [](const parser::OpenMPDispatchConstruct &c) { + return llvm::omp::OMPD_dispatch; + }, + [](const parser::OpenMPExecutableAllocate &c) { + return llvm::omp::OMPD_allocate; + }, + [](const parser::OpenMPLoopConstruct &c) { + return std::get( + std::get(c.t).t) + .v; + }, + [](const parser::OpenMPSectionConstruct &c) { + return llvm::omp::OMPD_section; + }, + [](const parser::OpenMPSectionsConstruct &c) { + return std::get( + std::get(c.t).t) + .v; + }, + [](const parser::OpenMPStandaloneConstruct &c) { + return common::visit( + common::visitors{ + [](const parser::OpenMPSimpleStandaloneConstruct &c) { + return c.v.DirId(); + }, + [](const parser::OpenMPFlushConstruct &c) { + return llvm::omp::OMPD_flush; + }, + [](const parser::OpenMPCancelConstruct &c) { + return llvm::omp::OMPD_cancel; + }, + [](const parser::OpenMPCancellationPointConstruct &c) { + return llvm::omp::OMPD_cancellation_point; + }, + [](const parser::OmpMetadirectiveDirective &c) { + return llvm::omp::OMPD_metadirective; + }, + [](const parser::OpenMPDepobjConstruct &c) { + return llvm::omp::OMPD_depobj; + }, + [](const parser::OpenMPInteropConstruct &c) { + return llvm::omp::OMPD_interop; + }}, + c.u); + }, + [](const parser::OpenMPUtilityConstruct &c) { + return common::visit( + common::visitors{[](const parser::OmpErrorDirective &c) { + return llvm::omp::OMPD_error; + }, + [](const parser::OmpNothingDirective &c) { + return llvm::omp::OMPD_nothing; + }}, + c.u); + }}, + ompConstruct.u); +} } // namespace omp } // namespace lower } // namespace Fortran diff --git a/flang/lib/Lower/OpenMP/Utils.h b/flang/lib/Lower/OpenMP/Utils.h index 1526bd4e90233..8e3ad5c3452e2 100644 --- a/flang/lib/Lower/OpenMP/Utils.h +++ b/flang/lib/Lower/OpenMP/Utils.h @@ -166,6 +166,9 @@ bool collectLoopRelatedInfo( lower::pft::Evaluation &eval, const omp::List &clauses, mlir::omp::LoopRelatedClauseOps &result, llvm::SmallVectorImpl &iv); + +llvm::omp::Directive +extractOmpDirective(const parser::OpenMPConstruct &ompConstruct); } // namespace omp } // namespace lower } // namespace Fortran diff --git a/flang/lib/Lower/Runtime.cpp b/flang/lib/Lower/Runtime.cpp index 2be5ef76e46b8..fc59a2414d539 100644 --- a/flang/lib/Lower/Runtime.cpp +++ b/flang/lib/Lower/Runtime.cpp @@ -43,7 +43,7 @@ static void genUnreachable(fir::FirOpBuilder &builder, mlir::Location loc) { mlir::acc::OpenACCDialect::getDialectNamespace()) Fortran::lower::genOpenACCTerminator(builder, parentOp, loc); else - builder.create(loc); + fir::UnreachableOp::create(builder, loc); mlir::Block *newBlock = curBlock->splitBlock(builder.getInsertionPoint()); builder.setInsertionPointToStart(newBlock); } @@ -118,7 +118,7 @@ void Fortran::lower::genStopStatement( loc, calleeType.getInput(operands.size()), 0)); } - builder.create(loc, callee, operands); + fir::CallOp::create(builder, loc, callee, operands); auto blockIsUnterminated = [&builder]() { mlir::Block *currentBlock = builder.getBlock(); return currentBlock->empty() || @@ -134,7 +134,7 @@ void Fortran::lower::genFailImageStatement( mlir::Location loc = converter.getCurrentLocation(); mlir::func::FuncOp callee = fir::runtime::getRuntimeFunc(loc, builder); - builder.create(loc, callee, std::nullopt); + fir::CallOp::create(builder, loc, callee, mlir::ValueRange{}); genUnreachable(builder, loc); } @@ -199,7 +199,7 @@ void Fortran::lower::genPauseStatement( mlir::Location loc = converter.getCurrentLocation(); mlir::func::FuncOp callee = fir::runtime::getRuntimeFunc(loc, builder); - builder.create(loc, callee, std::nullopt); + fir::CallOp::create(builder, loc, callee, mlir::ValueRange{}); } void Fortran::lower::genPointerAssociate(fir::FirOpBuilder &builder, @@ -210,17 +210,18 @@ void Fortran::lower::genPointerAssociate(fir::FirOpBuilder &builder, fir::runtime::getRuntimeFunc(loc, builder); llvm::SmallVector args = fir::runtime::createArguments( builder, loc, func.getFunctionType(), pointer, target); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } -void Fortran::lower::genPointerAssociateRemapping(fir::FirOpBuilder &builder, - mlir::Location loc, - mlir::Value pointer, - mlir::Value target, - mlir::Value bounds) { +void Fortran::lower::genPointerAssociateRemapping( + fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value pointer, + mlir::Value target, mlir::Value bounds, bool isMonomorphic) { mlir::func::FuncOp func = - fir::runtime::getRuntimeFunc(loc, - builder); + isMonomorphic + ? fir::runtime::getRuntimeFunc(loc, builder) + : fir::runtime::getRuntimeFunc( + loc, builder); auto fTy = func.getFunctionType(); auto sourceFile = fir::factory::locationToFilename(builder, loc); auto sourceLine = @@ -228,7 +229,7 @@ void Fortran::lower::genPointerAssociateRemapping(fir::FirOpBuilder &builder, llvm::SmallVector args = fir::runtime::createArguments( builder, loc, func.getFunctionType(), pointer, target, bounds, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void Fortran::lower::genPointerAssociateLowerBounds(fir::FirOpBuilder &builder, @@ -241,5 +242,5 @@ void Fortran::lower::genPointerAssociateLowerBounds(fir::FirOpBuilder &builder, loc, builder); llvm::SmallVector args = fir::runtime::createArguments( builder, loc, func.getFunctionType(), pointer, target, lbounds); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } diff --git a/flang/lib/Lower/Support/PrivateReductionUtils.cpp b/flang/lib/Lower/Support/PrivateReductionUtils.cpp index c3a5b6101ce00..fff060b79c9fe 100644 --- a/flang/lib/Lower/Support/PrivateReductionUtils.cpp +++ b/flang/lib/Lower/Support/PrivateReductionUtils.cpp @@ -75,9 +75,9 @@ static void createCleanupRegion(Fortran::lower::AbstractConverter &converter, /*mutableProperties=*/{}}; Fortran::lower::genDeallocateIfAllocated(converter, mutableBox, loc); if (isDoConcurrent) - builder.create(loc); + fir::YieldOp::create(builder, loc); else - builder.create(loc); + mlir::omp::YieldOp::create(builder, loc); return; } } @@ -97,18 +97,18 @@ static void createCleanupRegion(Fortran::lower::AbstractConverter &converter, hlfir::genVariableRawAddress(loc, builder, hlfir::Entity{arg}); mlir::Value isAllocated = builder.genIsNotNullAddr(loc, addr); fir::IfOp ifOp = - builder.create(loc, isAllocated, /*withElseRegion=*/false); + fir::IfOp::create(builder, loc, isAllocated, /*withElseRegion=*/false); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); mlir::Value cast = builder.createConvert( loc, fir::HeapType::get(fir::dyn_cast_ptrEleTy(addr.getType())), addr); - builder.create(loc, cast); + fir::FreeMemOp::create(builder, loc, cast); builder.setInsertionPointAfter(ifOp); if (isDoConcurrent) - builder.create(loc); + fir::YieldOp::create(builder, loc); else - builder.create(loc); + mlir::omp::YieldOp::create(builder, loc); return; } @@ -122,11 +122,11 @@ static void createCleanupRegion(Fortran::lower::AbstractConverter &converter, auto heapTy = fir::HeapType::get(refTy.getEleTy()); addr = builder.createConvert(loc, heapTy, addr); - builder.create(loc, addr); + fir::FreeMemOp::create(builder, loc, addr); if (isDoConcurrent) - builder.create(loc); + fir::YieldOp::create(builder, loc); else - builder.create(loc); + mlir::omp::YieldOp::create(builder, loc); return; } @@ -172,7 +172,7 @@ fir::ShapeShiftOp Fortran::lower::getShapeShift( // OpenACC does mlir::Value dim = builder.createIntegerConstant(loc, idxTy, i); auto dimInfo = - builder.create(loc, idxTy, idxTy, idxTy, box, dim); + fir::BoxDimsOp::create(builder, loc, idxTy, idxTy, idxTy, box, dim); lbAndExtents.push_back(useDefaultLowerBounds ? one() : dimInfo.getLowerBound()); lbAndExtents.push_back(dimInfo.getExtent()); @@ -181,7 +181,7 @@ fir::ShapeShiftOp Fortran::lower::getShapeShift( auto shapeShiftTy = fir::ShapeShiftType::get(builder.getContext(), rank); auto shapeShift = - builder.create(loc, shapeShiftTy, lbAndExtents); + fir::ShapeShiftOp::create(builder, loc, shapeShiftTy, lbAndExtents); return shapeShift; } @@ -270,7 +270,7 @@ static mlir::Value generateZeroShapeForRank(fir::FirOpBuilder &builder, mlir::SmallVector dims; dims.resize(rank, zero); mlir::Type shapeTy = fir::ShapeType::get(builder.getContext(), rank); - return builder.create(loc, shapeTy, dims); + return fir::ShapeOp::create(builder, loc, shapeTy, dims); } namespace { @@ -341,9 +341,9 @@ class PopulateInitAndCleanupRegionsHelper { void createYield(mlir::Value ret) { if (isDoConcurrent) - builder.create(loc, ret); + fir::YieldOp::create(builder, loc, ret); else - builder.create(loc, ret); + mlir::omp::YieldOp::create(builder, loc, ret); } void initTrivialType() { @@ -392,9 +392,9 @@ void PopulateInitAndCleanupRegionsHelper::initBoxedPrivatePointer( // Just incase, do initialize the box with a null value mlir::Value null = builder.createNullConstant(loc, boxTy.getEleTy()); mlir::Value nullBox; - nullBox = builder.create(loc, boxTy, null, shape, - /*slice=*/mlir::Value{}, lenParams); - builder.create(loc, nullBox, allocatedPrivVarArg); + nullBox = fir::EmboxOp::create(builder, loc, boxTy, null, shape, + /*slice=*/mlir::Value{}, lenParams); + fir::StoreOp::create(builder, loc, nullBox, allocatedPrivVarArg); createYield(allocatedPrivVarArg); } /// Check if an allocatable box is unallocated. If so, initialize the boxAlloca @@ -410,10 +410,10 @@ void PopulateInitAndCleanupRegionsHelper::initBoxedPrivatePointer( /// } /// omp.yield %box_alloca fir::IfOp PopulateInitAndCleanupRegionsHelper::handleNullAllocatable() { - mlir::Value addr = builder.create(loc, getLoadedMoldArg()); + mlir::Value addr = fir::BoxAddrOp::create(builder, loc, getLoadedMoldArg()); mlir::Value isNotAllocated = builder.genIsNullAddr(loc, addr); - fir::IfOp ifOp = builder.create(loc, isNotAllocated, - /*withElseRegion=*/true); + fir::IfOp ifOp = fir::IfOp::create(builder, loc, isNotAllocated, + /*withElseRegion=*/true); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); // Just embox the null address and return. // We have to give the embox a shape so that the LLVM box structure has the @@ -421,9 +421,9 @@ fir::IfOp PopulateInitAndCleanupRegionsHelper::handleNullAllocatable() { mlir::Value shape = generateZeroShapeForRank(builder, loc, moldArg); mlir::Value nullBox = - builder.create(loc, valType, addr, shape, - /*slice=*/mlir::Value{}, lenParams); - builder.create(loc, nullBox, allocatedPrivVarArg); + fir::EmboxOp::create(builder, loc, valType, addr, shape, + /*slice=*/mlir::Value{}, lenParams); + fir::StoreOp::create(builder, loc, nullBox, allocatedPrivVarArg); return ifOp; } @@ -442,14 +442,14 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedScalar( /*shape=*/{}, lenParams); if (scalarInitValue) builder.createStoreWithConvert(loc, scalarInitValue, valAlloc); - mlir::Value box = builder.create( - loc, valType, valAlloc, /*shape=*/mlir::Value{}, - /*slice=*/mlir::Value{}, lenParams); + mlir::Value box = fir::EmboxOp::create(builder, loc, valType, valAlloc, + /*shape=*/mlir::Value{}, + /*slice=*/mlir::Value{}, lenParams); initializeIfDerivedTypeBox( builder, loc, box, getLoadedMoldArg(), needsInitialization, /*isFirstPrivate=*/kind == DeclOperationKind::FirstPrivateOrLocalInit); fir::StoreOp lastOp = - builder.create(loc, box, allocatedPrivVarArg); + fir::StoreOp::create(builder, loc, box, allocatedPrivVarArg); createCleanupRegion(converter, loc, argType, cleanupRegion, sym, isDoConcurrent); @@ -483,14 +483,15 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray( fir::ShapeShiftOp shape = getShapeShift(builder, loc, source, cannotHaveNonDefaultLowerBounds); mlir::Type arrayType = source.getElementOrSequenceType(); - mlir::Value allocatedArray = builder.create( - loc, arrayType, /*typeparams=*/mlir::ValueRange{}, shape.getExtents()); - mlir::Value firClass = builder.create(loc, source.getType(), - allocatedArray, shape); + mlir::Value allocatedArray = fir::AllocMemOp::create( + builder, loc, arrayType, /*typeparams=*/mlir::ValueRange{}, + shape.getExtents()); + mlir::Value firClass = fir::EmboxOp::create(builder, loc, source.getType(), + allocatedArray, shape); initializeIfDerivedTypeBox( builder, loc, firClass, source, needsInitialization, /*isFirstprivate=*/kind == DeclOperationKind::FirstPrivateOrLocalInit); - builder.create(loc, firClass, allocatedPrivVarArg); + fir::StoreOp::create(builder, loc, firClass, allocatedPrivVarArg); if (ifUnallocated) builder.setInsertionPointAfter(ifUnallocated); createYield(allocatedPrivVarArg); @@ -543,22 +544,21 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray( if (mlir::isa(temp.getType())) // the box created by the declare form createTempFromMold is missing // lower bounds info - box = builder.create(loc, boxType, temp, shapeShift, - /*shift=*/mlir::Value{}); + box = fir::ReboxOp::create(builder, loc, boxType, temp, shapeShift, + /*shift=*/mlir::Value{}); else - box = builder.create( - loc, boxType, temp, shapeShift, - /*slice=*/mlir::Value{}, - /*typeParams=*/llvm::ArrayRef{}); + box = fir::EmboxOp::create(builder, loc, boxType, temp, shapeShift, + /*slice=*/mlir::Value{}, + /*typeParams=*/llvm::ArrayRef{}); if (scalarInitValue) - builder.create(loc, scalarInitValue, box); + hlfir::AssignOp::create(builder, loc, scalarInitValue, box); initializeIfDerivedTypeBox( builder, loc, box, getLoadedMoldArg(), needsInitialization, /*isFirstPrivate=*/kind == DeclOperationKind::FirstPrivateOrLocalInit); - builder.create(loc, box, allocatedPrivVarArg); + fir::StoreOp::create(builder, loc, box, allocatedPrivVarArg); if (ifUnallocated) builder.setInsertionPointAfter(ifUnallocated); createYield(allocatedPrivVarArg); @@ -596,8 +596,8 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupUnboxedDerivedType( builder.setInsertionPointToStart(initBlock); mlir::Type boxedTy = fir::BoxType::get(valType); mlir::Value newBox = - builder.create(loc, boxedTy, allocatedPrivVarArg); - mlir::Value moldBox = builder.create(loc, boxedTy, moldArg); + fir::EmboxOp::create(builder, loc, boxedTy, allocatedPrivVarArg); + mlir::Value moldBox = fir::EmboxOp::create(builder, loc, boxedTy, moldArg); initializeIfDerivedTypeBox(builder, loc, newBox, moldBox, needsInitialization, /*isFirstPrivate=*/kind == DeclOperationKind::FirstPrivateOrLocalInit); diff --git a/flang/lib/Lower/Support/ReductionProcessor.cpp b/flang/lib/Lower/Support/ReductionProcessor.cpp index c0be1e229f825..80c32d066a38d 100644 --- a/flang/lib/Lower/Support/ReductionProcessor.cpp +++ b/flang/lib/Lower/Support/ReductionProcessor.cpp @@ -260,20 +260,20 @@ ReductionProcessor::getReductionInitValue(mlir::Location loc, mlir::Type type, initIm); } if (mlir::isa(type)) - return builder.create( - loc, type, + return mlir::arith::ConstantOp::create( + builder, loc, type, builder.getFloatAttr(type, (double)getOperationIdentity(redId, loc))); if (mlir::isa(type)) { - mlir::Value intConst = builder.create( - loc, builder.getI1Type(), + mlir::Value intConst = mlir::arith::ConstantOp::create( + builder, loc, builder.getI1Type(), builder.getIntegerAttr(builder.getI1Type(), getOperationIdentity(redId, loc))); return builder.createConvert(loc, type, intConst); } - return builder.create( - loc, type, + return mlir::arith::ConstantOp::create( + builder, loc, type, builder.getIntegerAttr(type, getOperationIdentity(redId, loc))); case ReductionIdentifier::ID: case ReductionIdentifier::USER_DEF_OP: @@ -301,15 +301,15 @@ mlir::Value ReductionProcessor::createScalarCombiner( break; case ReductionIdentifier::IOR: assert((type.isIntOrIndex()) && "only integer is expected"); - reductionOp = builder.create(loc, op1, op2); + reductionOp = mlir::arith::OrIOp::create(builder, loc, op1, op2); break; case ReductionIdentifier::IEOR: assert((type.isIntOrIndex()) && "only integer is expected"); - reductionOp = builder.create(loc, op1, op2); + reductionOp = mlir::arith::XOrIOp::create(builder, loc, op1, op2); break; case ReductionIdentifier::IAND: assert((type.isIntOrIndex()) && "only integer is expected"); - reductionOp = builder.create(loc, op1, op2); + reductionOp = mlir::arith::AndIOp::create(builder, loc, op1, op2); break; case ReductionIdentifier::ADD: reductionOp = @@ -325,7 +325,8 @@ mlir::Value ReductionProcessor::createScalarCombiner( mlir::Value op1I1 = builder.createConvert(loc, builder.getI1Type(), op1); mlir::Value op2I1 = builder.createConvert(loc, builder.getI1Type(), op2); - mlir::Value andiOp = builder.create(loc, op1I1, op2I1); + mlir::Value andiOp = + mlir::arith::AndIOp::create(builder, loc, op1I1, op2I1); reductionOp = builder.createConvert(loc, type, andiOp); break; @@ -334,7 +335,7 @@ mlir::Value ReductionProcessor::createScalarCombiner( mlir::Value op1I1 = builder.createConvert(loc, builder.getI1Type(), op1); mlir::Value op2I1 = builder.createConvert(loc, builder.getI1Type(), op2); - mlir::Value oriOp = builder.create(loc, op1I1, op2I1); + mlir::Value oriOp = mlir::arith::OrIOp::create(builder, loc, op1I1, op2I1); reductionOp = builder.createConvert(loc, type, oriOp); break; @@ -343,8 +344,8 @@ mlir::Value ReductionProcessor::createScalarCombiner( mlir::Value op1I1 = builder.createConvert(loc, builder.getI1Type(), op1); mlir::Value op2I1 = builder.createConvert(loc, builder.getI1Type(), op2); - mlir::Value cmpiOp = builder.create( - loc, mlir::arith::CmpIPredicate::eq, op1I1, op2I1); + mlir::Value cmpiOp = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, op1I1, op2I1); reductionOp = builder.createConvert(loc, type, cmpiOp); break; @@ -353,8 +354,8 @@ mlir::Value ReductionProcessor::createScalarCombiner( mlir::Value op1I1 = builder.createConvert(loc, builder.getI1Type(), op1); mlir::Value op2I1 = builder.createConvert(loc, builder.getI1Type(), op2); - mlir::Value cmpiOp = builder.create( - loc, mlir::arith::CmpIPredicate::ne, op1I1, op2I1); + mlir::Value cmpiOp = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::ne, op1I1, op2I1); reductionOp = builder.createConvert(loc, type, cmpiOp); break; @@ -370,9 +371,9 @@ template static void genYield(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value yieldedValue) { if constexpr (std::is_same_v) - builder.create(loc, yieldedValue); + mlir::omp::YieldOp::create(builder, loc, yieldedValue); else - builder.create(loc, yieldedValue); + fir::YieldOp::create(builder, loc, yieldedValue); } /// Create reduction combiner region for reduction variables which are boxed @@ -393,24 +394,24 @@ static void genBoxCombiner(fir::FirOpBuilder &builder, mlir::Location loc, // load fir.ref> mlir::Value lhsAddr = lhs; - lhs = builder.create(loc, lhs); - rhs = builder.create(loc, rhs); + lhs = fir::LoadOp::create(builder, loc, lhs); + rhs = fir::LoadOp::create(builder, loc, rhs); if ((heapTy || ptrTy) && !seqTy) { // get box contents (heap pointers) - lhs = builder.create(loc, lhs); - rhs = builder.create(loc, rhs); + lhs = fir::BoxAddrOp::create(builder, loc, lhs); + rhs = fir::BoxAddrOp::create(builder, loc, rhs); mlir::Value lhsValAddr = lhs; // load heap pointers - lhs = builder.create(loc, lhs); - rhs = builder.create(loc, rhs); + lhs = fir::LoadOp::create(builder, loc, lhs); + rhs = fir::LoadOp::create(builder, loc, rhs); mlir::Type eleTy = heapTy ? heapTy.getEleTy() : ptrTy.getEleTy(); mlir::Value result = ReductionProcessor::createScalarCombiner( builder, loc, redId, eleTy, lhs, rhs); - builder.create(loc, result, lhsValAddr); + fir::StoreOp::create(builder, loc, result, lhsValAddr); genYield(builder, loc, lhsAddr); return; } @@ -437,17 +438,17 @@ static void genBoxCombiner(fir::FirOpBuilder &builder, mlir::Location loc, builder.setInsertionPointToStart(nest.body); const bool seqIsVolatile = fir::isa_volatile_type(seqTy.getEleTy()); mlir::Type refTy = fir::ReferenceType::get(seqTy.getEleTy(), seqIsVolatile); - auto lhsEleAddr = builder.create( - loc, refTy, lhs, shapeShift, /*slice=*/mlir::Value{}, + auto lhsEleAddr = fir::ArrayCoorOp::create( + builder, loc, refTy, lhs, shapeShift, /*slice=*/mlir::Value{}, nest.oneBasedIndices, /*typeparms=*/mlir::ValueRange{}); - auto rhsEleAddr = builder.create( - loc, refTy, rhs, shapeShift, /*slice=*/mlir::Value{}, + auto rhsEleAddr = fir::ArrayCoorOp::create( + builder, loc, refTy, rhs, shapeShift, /*slice=*/mlir::Value{}, nest.oneBasedIndices, /*typeparms=*/mlir::ValueRange{}); - auto lhsEle = builder.create(loc, lhsEleAddr); - auto rhsEle = builder.create(loc, rhsEleAddr); + auto lhsEle = fir::LoadOp::create(builder, loc, lhsEleAddr); + auto rhsEle = fir::LoadOp::create(builder, loc, rhsEleAddr); mlir::Value scalarReduction = ReductionProcessor::createScalarCombiner( builder, loc, redId, refTy, lhsEle, rhsEle); - builder.create(loc, scalarReduction, lhsEleAddr); + fir::StoreOp::create(builder, loc, scalarReduction, lhsEleAddr); builder.setInsertionPointAfter(nest.outerOp); genYield(builder, loc, lhsAddr); @@ -468,7 +469,7 @@ static void genCombiner(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value result = ReductionProcessor::createScalarCombiner( builder, loc, redId, ty, lhsLoaded, rhsLoaded); if (isByRef) { - builder.create(loc, result, lhs); + fir::StoreOp::create(builder, loc, result, lhs); genYield(builder, loc, lhs); } else { genYield(builder, loc, result); @@ -539,7 +540,7 @@ static void createReductionAllocAndInitRegions( if (isByRef) { // alloc region builder.setInsertionPointToEnd(allocBlock); - mlir::Value alloca = builder.create(loc, ty); + mlir::Value alloca = fir::AllocaOp::create(builder, loc, ty); yield(alloca); return; } @@ -551,7 +552,7 @@ static void createReductionAllocAndInitRegions( // alloc region builder.setInsertionPointToEnd(allocBlock); - mlir::Value boxAlloca = builder.create(loc, ty); + mlir::Value boxAlloca = fir::AllocaOp::create(builder, loc, ty); yield(boxAlloca); } @@ -575,7 +576,7 @@ OpType ReductionProcessor::createDeclareReduction( if (!isByRef) type = valTy; - decl = modBuilder.create(loc, reductionOpName, type); + decl = OpType::create(modBuilder, loc, reductionOpName, type); createReductionAllocAndInitRegions(converter, loc, decl, redId, type, isByRef); @@ -672,8 +673,8 @@ void ReductionProcessor::processReductionArguments( // Always pass the box by reference so that the OpenMP dialect // verifiers don't need to know anything about fir.box auto alloca = - builder.create(currentLocation, box.getType()); - builder.create(currentLocation, box, alloca); + fir::AllocaOp::create(builder, currentLocation, box.getType()); + fir::StoreOp::create(builder, currentLocation, box, alloca); symVal = alloca; } else if (mlir::isa(symVal.getType())) { @@ -683,9 +684,9 @@ void ReductionProcessor::processReductionArguments( auto oldIP = builder.saveInsertionPoint(); builder.setInsertionPointToStart(builder.getAllocaBlock()); auto alloca = - builder.create(currentLocation, symVal.getType()); + fir::AllocaOp::create(builder, currentLocation, symVal.getType()); builder.restoreInsertionPoint(oldIP); - builder.create(currentLocation, symVal, alloca); + fir::StoreOp::create(builder, currentLocation, symVal, alloca); symVal = alloca; } diff --git a/flang/lib/Lower/Support/Utils.cpp b/flang/lib/Lower/Support/Utils.cpp index b9d2574a76ad0..881401e11fee4 100644 --- a/flang/lib/Lower/Support/Utils.cpp +++ b/flang/lib/Lower/Support/Utils.cpp @@ -702,9 +702,10 @@ void privatizeSymbol( // Boxes should be passed by reference into nested regions: auto oldIP = firOpBuilder.saveInsertionPoint(); firOpBuilder.setInsertionPointToStart(firOpBuilder.getAllocaBlock()); - auto alloca = firOpBuilder.create(symLoc, privVal.getType()); + auto alloca = + fir::AllocaOp::create(firOpBuilder, symLoc, privVal.getType()); firOpBuilder.restoreInsertionPoint(oldIP); - firOpBuilder.create(symLoc, privVal, alloca); + fir::StoreOp::create(firOpBuilder, symLoc, privVal, alloca); privVal = alloca; } @@ -726,15 +727,15 @@ void privatizeSymbol( OpType result; if constexpr (std::is_same_v) { - result = firOpBuilder.create( - symLoc, uniquePrivatizerName, allocType, + result = OpType::create( + firOpBuilder, symLoc, uniquePrivatizerName, allocType, emitCopyRegion ? mlir::omp::DataSharingClauseType::FirstPrivate : mlir::omp::DataSharingClauseType::Private); } else { - result = firOpBuilder.create( - symLoc, uniquePrivatizerName, allocType, - emitCopyRegion ? fir::LocalitySpecifierType::LocalInit - : fir::LocalitySpecifierType::Local); + result = + OpType::create(firOpBuilder, symLoc, uniquePrivatizerName, allocType, + emitCopyRegion ? fir::LocalitySpecifierType::LocalInit + : fir::LocalitySpecifierType::Local); } fir::ExtendedValue symExV = converter.getSymbolExtendedValue(*sym); @@ -815,12 +816,12 @@ void privatizeSymbol( copyFirstPrivateSymbol(converter, symToPrivatize, &ip); if constexpr (std::is_same_v) { - firOpBuilder.create( - hsb.getAddr().getLoc(), + mlir::omp::YieldOp::create( + firOpBuilder, hsb.getAddr().getLoc(), symTable.shallowLookupSymbol(*symToPrivatize).getAddr()); } else { - firOpBuilder.create( - hsb.getAddr().getLoc(), + fir::YieldOp::create( + firOpBuilder, hsb.getAddr().getLoc(), symTable.shallowLookupSymbol(*symToPrivatize).getAddr()); } } diff --git a/flang/lib/Lower/VectorSubscripts.cpp b/flang/lib/Lower/VectorSubscripts.cpp index 389a89ddcf102..4d1d6fb28b365 100644 --- a/flang/lib/Lower/VectorSubscripts.cpp +++ b/flang/lib/Lower/VectorSubscripts.cpp @@ -121,8 +121,9 @@ class VectorSubscriptBoxBuilder { if (recTy.getNumLenParams() != 0) TODO(loc, "threading length parameters in field index op"); fir::FirOpBuilder &builder = converter.getFirOpBuilder(); - componentPath.emplace_back(builder.create( - loc, fldTy, componentName, recTy, /*typeParams*/ std::nullopt)); + componentPath.emplace_back( + fir::FieldIndexOp::create(builder, loc, fldTy, componentName, recTy, + /*typeParams=*/mlir::ValueRange{})); return fir::unwrapSequenceType(recTy.getType(componentName)); } @@ -269,16 +270,16 @@ mlir::Value Fortran::lower::VectorSubscriptBox::loopOverElementsBase( for (auto [lb, ub, step] : genLoopBounds(builder, loc)) { LoopType loop; if constexpr (std::is_same_v) { - loop = - builder.create(loc, lb, ub, step, initialCondition); + loop = fir::IterWhileOp::create(builder, loc, lb, ub, step, + initialCondition); initialCondition = loop.getIterateVar(); if (!outerLoop) outerLoop = loop; else - builder.create(loc, loop.getResult(0)); + fir::ResultOp::create(builder, loc, loop.getResult(0)); } else { - loop = - builder.create(loc, lb, ub, step, /*unordered=*/false); + loop = fir::DoLoopOp::create(builder, loc, lb, ub, step, + /*unordered=*/false); if (!outerLoop) outerLoop = loop; } @@ -293,7 +294,7 @@ mlir::Value Fortran::lower::VectorSubscriptBox::loopOverElementsBase( if constexpr (std::is_same_v) { auto res = elementalGenerator(elem); - builder.create(loc, res); + fir::ResultOp::create(builder, loc, res); builder.setInsertionPointAfter(outerLoop); return outerLoop.getResult(0); } else { @@ -326,7 +327,7 @@ Fortran::lower::VectorSubscriptBox::createSlice(fir::FirOpBuilder &builder, mlir::Type idxTy = builder.getIndexType(); llvm::SmallVector triples; mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1); - auto undef = builder.create(loc, idxTy); + auto undef = fir::UndefOp::create(builder, loc, idxTy); for (const LoweredSubscript &subscript : loweredSubscripts) Fortran::common::visit(Fortran::common::visitors{ [&](const LoweredTriplet &triplet) { @@ -346,7 +347,7 @@ Fortran::lower::VectorSubscriptBox::createSlice(fir::FirOpBuilder &builder, }, }, subscript); - return builder.create(loc, triples, componentPath); + return fir::SliceOp::create(builder, loc, triples, componentPath); } llvm::SmallVector> @@ -369,13 +370,13 @@ Fortran::lower::VectorSubscriptBox::genLoopBounds(fir::FirOpBuilder &builder, builder, loc, loweredBase, dimension, one); baseLb = builder.createConvert(loc, idxTy, baseLb); lb = baseLb; - ub = builder.create(loc, idxTy, extent, one); - ub = builder.create(loc, idxTy, ub, baseLb); + ub = mlir::arith::SubIOp::create(builder, loc, idxTy, extent, one); + ub = mlir::arith::AddIOp::create(builder, loc, idxTy, ub, baseLb); step = one; } else { const auto &vector = std::get(subscript); lb = zero; - ub = builder.create(loc, idxTy, vector.size, one); + ub = mlir::arith::SubIOp::create(builder, loc, idxTy, vector.size, one); step = one; } bounds.emplace_back(lb, ub, step); @@ -402,10 +403,10 @@ fir::ExtendedValue Fortran::lower::VectorSubscriptBox::getElementAt( mlir::Type vecEleTy = fir::unwrapSequenceType( fir::unwrapPassByRefType(vecBase.getType())); mlir::Type refTy = builder.getRefType(vecEleTy); - auto vecEltRef = builder.create( - loc, refTy, vecBase, vecIndex); + auto vecEltRef = fir::CoordinateOp::create(builder, loc, refTy, + vecBase, vecIndex); auto vecElt = - builder.create(loc, vecEleTy, vecEltRef); + fir::LoadOp::create(builder, loc, vecEleTy, vecEltRef); indexes.emplace_back(builder.createConvert(loc, idxTy, vecElt)); }, [&](const mlir::Value &i) { @@ -414,8 +415,8 @@ fir::ExtendedValue Fortran::lower::VectorSubscriptBox::getElementAt( }, subscript); mlir::Type refTy = builder.getRefType(getElementType()); - auto elementAddr = builder.create( - loc, refTy, fir::getBase(loweredBase), shape, slice, indexes, + auto elementAddr = fir::ArrayCoorOp::create( + builder, loc, refTy, fir::getBase(loweredBase), shape, slice, indexes, fir::getTypeParams(loweredBase)); fir::ExtendedValue element = fir::factory::arraySectionElementToExtendedValue( builder, loc, loweredBase, elementAddr, slice); diff --git a/flang/lib/Optimizer/Builder/CUFCommon.cpp b/flang/lib/Optimizer/Builder/CUFCommon.cpp index dcbf4991907bf..cf7588f275d22 100644 --- a/flang/lib/Optimizer/Builder/CUFCommon.cpp +++ b/flang/lib/Optimizer/Builder/CUFCommon.cpp @@ -25,8 +25,8 @@ mlir::gpu::GPUModuleOp cuf::getOrCreateGPUModule(mlir::ModuleOp mod, mlir::UnitAttr::get(ctx)); mlir::OpBuilder builder(ctx); - auto gpuMod = builder.create(mod.getLoc(), - cudaDeviceModuleName); + auto gpuMod = mlir::gpu::GPUModuleOp::create(builder, mod.getLoc(), + cudaDeviceModuleName); mlir::Block::iterator insertPt(mod.getBodyRegion().front().end()); symTab.insert(gpuMod, insertPt); return gpuMod; @@ -84,8 +84,8 @@ void cuf::genPointerSync(const mlir::Value box, fir::FirOpBuilder &builder) { if (auto globalOp = mod.lookupSymbol(addrOfOp.getSymbol())) { if (cuf::isRegisteredDeviceGlobal(globalOp)) { - builder.create(box.getLoc(), - addrOfOp.getSymbol()); + cuf::SyncDescriptorOp::create(builder, box.getLoc(), + addrOfOp.getSymbol()); } } } diff --git a/flang/lib/Optimizer/Builder/Character.cpp b/flang/lib/Optimizer/Builder/Character.cpp index 61428ac490a46..a096099a04fe8 100644 --- a/flang/lib/Optimizer/Builder/Character.cpp +++ b/flang/lib/Optimizer/Builder/Character.cpp @@ -112,8 +112,8 @@ fir::factory::CharacterExprHelper::materializeValue(mlir::Value str) { } auto len = builder.createIntegerConstant( loc, builder.getCharacterLengthType(), charTy.getLen()); - auto temp = builder.create(loc, charTy); - builder.create(loc, str, temp); + auto temp = fir::AllocaOp::create(builder, loc, charTy); + fir::StoreOp::create(builder, loc, str, temp); LLVM_DEBUG(llvm::dbgs() << "materialized as local: " << str << " -> (" << temp << ", " << len << ")\n"); return {temp, len}; @@ -163,7 +163,7 @@ fir::factory::CharacterExprHelper::toExtendedValue(mlir::Value character, } if (!boxCharLen) { auto unboxed = - builder.create(loc, refType, lenType, character); + fir::UnboxCharOp::create(builder, loc, refType, lenType, character); base = builder.createConvert(loc, refType, unboxed.getResult(0)); boxCharLen = unboxed.getResult(1); } @@ -208,7 +208,7 @@ fir::factory::CharacterExprHelper::createEmbox(const fir::CharBoxValue &box) { // not in memory. if (!fir::isa_ref_type(buff.getType())) { auto temp = builder.createTemporary(loc, buff.getType()); - builder.create(loc, buff, temp); + fir::StoreOp::create(builder, loc, buff, temp); buff = temp; } // fir.emboxchar only accepts scalar, cast array buffer to a scalar buffer. @@ -218,7 +218,7 @@ fir::factory::CharacterExprHelper::createEmbox(const fir::CharBoxValue &box) { // be used in boxchar. auto len = builder.createConvert(loc, builder.getCharacterLengthType(), box.getLen()); - return builder.create(loc, boxCharType, buff, len); + return fir::EmboxCharOp::create(builder, loc, boxCharType, buff, len); } fir::CharBoxValue fir::factory::CharacterExprHelper::toScalarCharacter( @@ -231,8 +231,8 @@ fir::CharBoxValue fir::factory::CharacterExprHelper::toScalarCharacter( auto lenType = builder.getCharacterLengthType(); auto len = builder.createConvert(loc, lenType, box.getLen()); for (auto extent : box.getExtents()) - len = builder.create( - loc, len, builder.createConvert(loc, lenType, extent)); + len = mlir::arith::MulIOp::create( + builder, loc, len, builder.createConvert(loc, lenType, extent)); // TODO: typeLen can be improved in compiled constant cases // TODO: allow bare fir.array<> (no ref) conversion here ? @@ -277,7 +277,7 @@ fir::factory::CharacterExprHelper::createElementAddr(mlir::Value buffer, auto coor = builder.createConvert(loc, coorTy, buffer); auto i = builder.createConvert(loc, builder.getIndexType(), index); - return builder.create(loc, singleRefTy, coor, i); + return fir::CoordinateOp::create(builder, loc, singleRefTy, coor, i); } /// Load a character out of `buff` from offset `index`. @@ -287,7 +287,7 @@ fir::factory::CharacterExprHelper::createLoadCharAt(mlir::Value buff, mlir::Value index) { LLVM_DEBUG(llvm::dbgs() << "load a char: " << buff << " type: " << buff.getType() << " at: " << index << '\n'); - return builder.create(loc, createElementAddr(buff, index)); + return fir::LoadOp::create(builder, loc, createElementAddr(buff, index)); } /// Store the singleton character `c` to `str` at offset `index`. @@ -299,7 +299,7 @@ void fir::factory::CharacterExprHelper::createStoreCharAt(mlir::Value str, << " type: " << str.getType() << " at: " << index << '\n'); auto addr = createElementAddr(str, index); - builder.create(loc, c, addr); + fir::StoreOp::create(builder, loc, c, addr); } // FIXME: this temp is useless... either fir.coordinate_of needs to @@ -311,8 +311,8 @@ mlir::Value fir::factory::CharacterExprHelper::getCharBoxBuffer( const fir::CharBoxValue &box) { auto buff = box.getBuffer(); if (fir::isa_char(buff.getType())) { - auto newBuff = builder.create(loc, buff.getType()); - builder.create(loc, buff, newBuff); + auto newBuff = fir::AllocaOp::create(builder, loc, buff.getType()); + fir::StoreOp::create(builder, loc, buff, newBuff); return newBuff; } return buff; @@ -339,19 +339,19 @@ void fir::factory::CharacterExprHelper::createCopy( auto kindBytes = builder.createIntegerConstant(loc, i64Ty, bytes); auto castCount = builder.createConvert(loc, i64Ty, count); auto totalBytes = - builder.create(loc, kindBytes, castCount); + mlir::arith::MulIOp::create(builder, loc, kindBytes, castCount); auto llvmPointerType = mlir::LLVM::LLVMPointerType::get(builder.getContext()); auto toPtr = builder.createConvert(loc, llvmPointerType, toBuff); auto fromPtr = builder.createConvert(loc, llvmPointerType, fromBuff); - builder.create(loc, toPtr, fromPtr, totalBytes, - isVolatile); + mlir::LLVM::MemmoveOp::create(builder, loc, toPtr, fromPtr, totalBytes, + isVolatile); return; } // Convert a CHARACTER of one KIND into a CHARACTER of another KIND. - builder.create(loc, src.getBuffer(), count, - dest.getBuffer()); + fir::CharConvertOp::create(builder, loc, src.getBuffer(), count, + dest.getBuffer()); } void fir::factory::CharacterExprHelper::createPadding( @@ -397,7 +397,7 @@ fir::CharBoxValue fir::factory::CharacterExprHelper::createTempFrom( } else { auto ref = builder.createConvert(loc, builder.getRefType(sourceTy), temp.getBuffer()); - builder.create(loc, charBox->getBuffer(), ref); + fir::StoreOp::create(builder, loc, charBox->getBuffer(), ref); } return temp; } @@ -412,23 +412,23 @@ void fir::factory::CharacterExprHelper::createLengthOneAssign( auto fromCharLen1RefTy = builder.getRefType(getSingletonCharType( builder.getContext(), getCharacterKind(fir::unwrapRefType(val.getType())))); - val = builder.create( - loc, builder.createConvert(loc, fromCharLen1RefTy, val)); + val = fir::LoadOp::create( + builder, loc, builder.createConvert(loc, fromCharLen1RefTy, val)); } auto toCharLen1Ty = getSingletonCharType(builder.getContext(), getCharacterKind(toTy)); val = builder.createConvert(loc, toCharLen1Ty, val); - builder.create( - loc, val, + fir::StoreOp::create( + builder, loc, val, builder.createConvert(loc, builder.getRefType(toCharLen1Ty), addr)); } /// Returns the minimum of integer mlir::Value \p a and \b. mlir::Value genMin(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value a, mlir::Value b) { - auto cmp = builder.create( - loc, mlir::arith::CmpIPredicate::slt, a, b); - return builder.create(loc, cmp, a, b); + auto cmp = mlir::arith::CmpIOp::create(builder, loc, + mlir::arith::CmpIPredicate::slt, a, b); + return mlir::arith::SelectOp::create(builder, loc, cmp, a, b); } void fir::factory::CharacterExprHelper::createAssign( @@ -479,7 +479,7 @@ void fir::factory::CharacterExprHelper::createAssign( if (!compileTimeSameLength) { auto one = builder.createIntegerConstant(loc, lhs.getLen().getType(), 1); auto maxPadding = - builder.create(loc, lhs.getLen(), one); + mlir::arith::SubIOp::create(builder, loc, lhs.getLen(), one); createPadding(lhs, copyCount, maxPadding); } } @@ -490,18 +490,19 @@ fir::CharBoxValue fir::factory::CharacterExprHelper::createConcatenate( lhs.getLen()); auto rhsLen = builder.createConvert(loc, builder.getCharacterLengthType(), rhs.getLen()); - mlir::Value len = builder.create(loc, lhsLen, rhsLen); + mlir::Value len = mlir::arith::AddIOp::create(builder, loc, lhsLen, rhsLen); auto temp = createCharacterTemp(getCharacterType(rhs), len); createCopy(temp, lhs, lhsLen); auto one = builder.createIntegerConstant(loc, len.getType(), 1); - auto upperBound = builder.create(loc, len, one); + auto upperBound = mlir::arith::SubIOp::create(builder, loc, len, one); auto lhsLenIdx = builder.createConvert(loc, builder.getIndexType(), lhsLen); auto fromBuff = getCharBoxBuffer(rhs); auto toBuff = getCharBoxBuffer(temp); fir::factory::DoLoopHelper{builder, loc}.createLoop( lhsLenIdx, upperBound, one, [&](fir::FirOpBuilder &bldr, mlir::Value index) { - auto rhsIndex = bldr.create(loc, index, lhsLenIdx); + auto rhsIndex = + mlir::arith::SubIOp::create(bldr, loc, index, lhsLenIdx); auto charVal = createLoadCharAt(fromBuff, rhsIndex); createStoreCharAt(toBuff, index, charVal); }); @@ -514,7 +515,7 @@ mlir::Value fir::factory::CharacterExprHelper::genSubstringBase( if (!one) one = builder.createIntegerConstant(loc, lowerBound.getType(), 1); auto offset = - builder.create(loc, lowerBound, one).getResult(); + mlir::arith::SubIOp::create(builder, loc, lowerBound, one).getResult(); auto addr = createElementAddr(stringRawAddr, offset); return builder.createConvert(loc, substringAddrType, addr); } @@ -545,19 +546,19 @@ fir::CharBoxValue fir::factory::CharacterExprHelper::createSubstring( mlir::Value substringLen; if (nbounds < 2) { substringLen = - builder.create(loc, box.getLen(), castBounds[0]); + mlir::arith::SubIOp::create(builder, loc, box.getLen(), castBounds[0]); } else { substringLen = - builder.create(loc, castBounds[1], castBounds[0]); + mlir::arith::SubIOp::create(builder, loc, castBounds[1], castBounds[0]); } - substringLen = builder.create(loc, substringLen, one); + substringLen = mlir::arith::AddIOp::create(builder, loc, substringLen, one); // Set length to zero if bounds were reversed (Fortran 2018 9.4.1) auto zero = builder.createIntegerConstant(loc, substringLen.getType(), 0); - auto cdt = builder.create( - loc, mlir::arith::CmpIPredicate::slt, substringLen, zero); + auto cdt = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::slt, substringLen, zero); substringLen = - builder.create(loc, cdt, zero, substringLen); + mlir::arith::SelectOp::create(builder, loc, cdt, zero, substringLen); return {substringRef, substringLen}; } @@ -573,11 +574,11 @@ fir::factory::CharacterExprHelper::createLenTrim(const fir::CharBoxValue &str) { auto zero = builder.createIntegerConstant(loc, indexType, 0); auto trueVal = builder.createIntegerConstant(loc, builder.getI1Type(), 1); auto blank = createBlankConstantCode(getCharacterType(str)); - mlir::Value lastChar = builder.create(loc, len, one); + mlir::Value lastChar = mlir::arith::SubIOp::create(builder, loc, len, one); auto iterWhile = - builder.create(loc, lastChar, zero, minusOne, trueVal, - /*returnFinalCount=*/false, lastChar); + fir::IterWhileOp::create(builder, loc, lastChar, zero, minusOne, trueVal, + /*returnFinalCount=*/false, lastChar); auto insPt = builder.saveInsertionPoint(); builder.setInsertionPointToStart(iterWhile.getBody()); auto index = iterWhile.getInductionVar(); @@ -586,17 +587,17 @@ fir::factory::CharacterExprHelper::createLenTrim(const fir::CharBoxValue &str) { auto elemAddr = createElementAddr(fromBuff, index); auto codeAddr = builder.createConvert(loc, builder.getRefType(blank.getType()), elemAddr); - auto c = builder.create(loc, codeAddr); - auto isBlank = builder.create( - loc, mlir::arith::CmpIPredicate::eq, blank, c); + auto c = fir::LoadOp::create(builder, loc, codeAddr); + auto isBlank = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, blank, c); llvm::SmallVector results = {isBlank, index}; - builder.create(loc, results); + fir::ResultOp::create(builder, loc, results); builder.restoreInsertionPoint(insPt); // Compute length after iteration (zero if all blanks) mlir::Value newLen = - builder.create(loc, iterWhile.getResult(1), one); - auto result = builder.create( - loc, iterWhile.getResult(0), zero, newLen); + mlir::arith::AddIOp::create(builder, loc, iterWhile.getResult(1), one); + auto result = mlir::arith::SelectOp::create( + builder, loc, iterWhile.getResult(0), zero, newLen); return builder.createConvert(loc, builder.getCharacterLengthType(), result); } @@ -606,7 +607,7 @@ fir::factory::CharacterExprHelper::createCharacterTemp(mlir::Type type, assert(len >= 0 && "expected positive length"); auto kind = recoverCharacterType(type).getFKind(); auto charType = fir::CharacterType::get(builder.getContext(), kind, len); - auto addr = builder.create(loc, charType); + auto addr = fir::AllocaOp::create(builder, loc, charType); auto mlirLen = builder.createIntegerConstant(loc, builder.getCharacterLengthType(), len); return {addr, mlirLen}; @@ -690,10 +691,10 @@ fir::factory::CharacterExprHelper::createSingletonFromCode(mlir::Value code, auto bits = builder.getKindMap().getCharacterBitsize(kind); auto intType = builder.getIntegerType(bits); auto cast = builder.createConvert(loc, intType, code); - auto undef = builder.create(loc, charType); + auto undef = fir::UndefOp::create(builder, loc, charType); auto zero = builder.getIntegerAttr(builder.getIndexType(), 0); - return builder.create(loc, charType, undef, cast, - builder.getArrayAttr(zero)); + return fir::InsertValueOp::create(builder, loc, charType, undef, cast, + builder.getArrayAttr(zero)); } mlir::Value fir::factory::CharacterExprHelper::extractCodeFromSingleton( @@ -703,8 +704,8 @@ mlir::Value fir::factory::CharacterExprHelper::extractCodeFromSingleton( auto bits = builder.getKindMap().getCharacterBitsize(type.getFKind()); auto intType = builder.getIntegerType(bits); auto zero = builder.getIntegerAttr(builder.getIndexType(), 0); - return builder.create(loc, intType, singleton, - builder.getArrayAttr(zero)); + return fir::ExtractValueOp::create(builder, loc, intType, singleton, + builder.getArrayAttr(zero)); } mlir::Value @@ -716,12 +717,12 @@ fir::factory::CharacterExprHelper::readLengthFromBox(mlir::Value box) { mlir::Value fir::factory::CharacterExprHelper::readLengthFromBox( mlir::Value box, fir::CharacterType charTy) { auto lenTy = builder.getCharacterLengthType(); - auto size = builder.create(loc, lenTy, box); + auto size = fir::BoxEleSizeOp::create(builder, loc, lenTy, box); auto bits = builder.getKindMap().getCharacterBitsize(charTy.getFKind()); auto width = bits / 8; if (width > 1) { auto widthVal = builder.createIntegerConstant(loc, lenTy, width); - return builder.create(loc, size, widthVal); + return mlir::arith::DivSIOp::create(builder, loc, size, widthVal); } return size; } @@ -748,18 +749,18 @@ fir::factory::extractCharacterProcedureTuple(fir::FirOpBuilder &builder, mlir::Value tuple, bool openBoxProc) { mlir::TupleType tupleType = mlir::cast(tuple.getType()); - mlir::Value addr = builder.create( - loc, tupleType.getType(0), tuple, + mlir::Value addr = fir::ExtractValueOp::create( + builder, loc, tupleType.getType(0), tuple, builder.getArrayAttr( {builder.getIntegerAttr(builder.getIndexType(), 0)})); mlir::Value proc = [&]() -> mlir::Value { if (openBoxProc) if (auto addrTy = mlir::dyn_cast(addr.getType())) - return builder.create(loc, addrTy.getEleTy(), addr); + return fir::BoxAddrOp::create(builder, loc, addrTy.getEleTy(), addr); return addr; }(); - mlir::Value len = builder.create( - loc, tupleType.getType(1), tuple, + mlir::Value len = fir::ExtractValueOp::create( + builder, loc, tupleType.getType(1), tuple, builder.getArrayAttr( {builder.getIntegerAttr(builder.getIndexType(), 1)})); return {proc, len}; @@ -773,14 +774,14 @@ mlir::Value fir::factory::createCharacterProcedureTuple( if (len) len = builder.createConvert(loc, tupleType.getType(1), len); else - len = builder.create(loc, tupleType.getType(1)); - mlir::Value tuple = builder.create(loc, tupleType); - tuple = builder.create( - loc, tupleType, tuple, addr, + len = fir::UndefOp::create(builder, loc, tupleType.getType(1)); + mlir::Value tuple = fir::UndefOp::create(builder, loc, tupleType); + tuple = fir::InsertValueOp::create( + builder, loc, tupleType, tuple, addr, builder.getArrayAttr( {builder.getIntegerAttr(builder.getIndexType(), 0)})); - tuple = builder.create( - loc, tupleType, tuple, len, + tuple = fir::InsertValueOp::create( + builder, loc, tupleType, tuple, len, builder.getArrayAttr( {builder.getIntegerAttr(builder.getIndexType(), 1)})); return tuple; @@ -827,10 +828,10 @@ fir::CharBoxValue fir::factory::CharacterExprHelper::createCharExtremum( auto currLen = builder.createConvert(loc, builder.getCharacterLengthType(), currChar.getLen()); // biggest len result - mlir::Value lhsBigger = builder.create( - loc, mlir::arith::CmpIPredicate::uge, biggestLen, currLen); - biggestLen = builder.create(loc, lhsBigger, - biggestLen, currLen); + mlir::Value lhsBigger = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::uge, biggestLen, currLen); + biggestLen = mlir::arith::SelectOp::create(builder, loc, lhsBigger, + biggestLen, currLen); auto cmp = predIsMin ? mlir::arith::CmpIPredicate::slt : mlir::arith::CmpIPredicate::sgt; @@ -843,10 +844,10 @@ fir::CharBoxValue fir::factory::CharacterExprHelper::createCharExtremum( resultBuf = builder.createConvert(loc, type, resultBuf); currBuf = builder.createConvert(loc, type, currBuf); - resultBuf = builder.create(loc, resultCmp, currBuf, - resultBuf); - resultLen = builder.create(loc, resultCmp, currLen, - resultLen); + resultBuf = mlir::arith::SelectOp::create(builder, loc, resultCmp, currBuf, + resultBuf); + resultLen = mlir::arith::SelectOp::create(builder, loc, resultCmp, currLen, + resultLen); } // now that we know the lexicographically biggest/smallest char and which char @@ -876,7 +877,7 @@ fir::factory::convertCharacterKind(fir::FirOpBuilder &builder, // As a value, it ought to have a constant LEN value. assert(charTy.hasConstantLen() && "must have constant length"); mlir::Value tmp = builder.createTemporary(loc, charTy); - builder.create(loc, boxCharAddr, tmp); + fir::StoreOp::create(builder, loc, boxCharAddr, tmp); boxCharAddr = tmp; } auto fromBits = kindMap.getCharacterBitsize( @@ -886,13 +887,13 @@ fir::factory::convertCharacterKind(fir::FirOpBuilder &builder, // Scale by relative ratio to give a buffer of the same length. auto ratio = builder.createIntegerConstant(loc, bufferSize.getType(), fromBits / toBits); - bufferSize = builder.create(loc, bufferSize, ratio); + bufferSize = mlir::arith::MulIOp::create(builder, loc, bufferSize, ratio); } mlir::Type toType = fir::CharacterType::getUnknownLen(builder.getContext(), toKind); auto dest = builder.createTemporary(loc, toType, /*name=*/{}, /*shape=*/{}, mlir::ValueRange{bufferSize}); - builder.create(loc, boxCharAddr, srcBoxChar.getLen(), - dest); + fir::CharConvertOp::create(builder, loc, boxCharAddr, srcBoxChar.getLen(), + dest); return fir::CharBoxValue{dest, srcBoxChar.getLen()}; } diff --git a/flang/lib/Optimizer/Builder/Complex.cpp b/flang/lib/Optimizer/Builder/Complex.cpp index 69f97dd654ce0..61de9880774ac 100644 --- a/flang/lib/Optimizer/Builder/Complex.cpp +++ b/flang/lib/Optimizer/Builder/Complex.cpp @@ -24,7 +24,7 @@ mlir::Type fir::factory::Complex::getComplexPartType(mlir::Value cplx) const { mlir::Value fir::factory::Complex::createComplex(mlir::Type cplxTy, mlir::Value real, mlir::Value imag) { - mlir::Value und = builder.create(loc, cplxTy); + mlir::Value und = fir::UndefOp::create(builder, loc, cplxTy); return insert(insert(und, real), imag); } diff --git a/flang/lib/Optimizer/Builder/DoLoopHelper.cpp b/flang/lib/Optimizer/Builder/DoLoopHelper.cpp index 4b12e281b5153..0ec91d5883b92 100644 --- a/flang/lib/Optimizer/Builder/DoLoopHelper.cpp +++ b/flang/lib/Optimizer/Builder/DoLoopHelper.cpp @@ -20,7 +20,7 @@ fir::factory::DoLoopHelper::createLoop(mlir::Value lb, mlir::Value ub, auto ubi = builder.convertToIndexType(loc, ub); assert(step && "step must be an actual Value"); auto inc = builder.convertToIndexType(loc, step); - auto loop = builder.create(loc, lbi, ubi, inc); + auto loop = fir::DoLoopOp::create(builder, loc, lbi, ubi, inc); auto insertPt = builder.saveInsertionPoint(); builder.setInsertionPointToStart(loop.getBody()); auto index = loop.getInductionVar(); @@ -43,6 +43,6 @@ fir::factory::DoLoopHelper::createLoop(mlir::Value count, auto indexType = builder.getIndexType(); auto zero = builder.createIntegerConstant(loc, indexType, 0); auto one = builder.createIntegerConstant(loc, count.getType(), 1); - auto up = builder.create(loc, count, one); + auto up = mlir::arith::SubIOp::create(builder, loc, count, one); return createLoop(zero, up, one, bodyGenerator); } diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp index acd5a88a2582d..eaad54eb9eec2 100644 --- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -406,10 +406,10 @@ mlir::Value fir::FirOpBuilder::genTempDeclareOp( llvm::ArrayRef typeParams, fir::FortranVariableFlagsAttr fortranAttrs) { auto nameAttr = mlir::StringAttr::get(builder.getContext(), name); - return builder.create(loc, memref.getType(), memref, shape, - typeParams, - /*dummy_scope=*/nullptr, nameAttr, - fortranAttrs, cuf::DataAttributeAttr{}); + return fir::DeclareOp::create(builder, loc, memref.getType(), memref, shape, + typeParams, + /*dummy_scope=*/nullptr, nameAttr, fortranAttrs, + cuf::DataAttributeAttr{}); } mlir::Value fir::FirOpBuilder::genStackSave(mlir::Location loc) { @@ -585,7 +585,7 @@ mlir::Value fir::factory::createConvert(mlir::OpBuilder &builder, mlir::cast(val.getType()).getTypeList() == mlir::cast(toTy).getTypeList()) && "incompatible record types"); - return builder.create(loc, toTy, val); + return fir::ConvertOp::create(builder, loc, toTy, val); } return val; } @@ -620,7 +620,7 @@ fir::StringLitOp fir::FirOpBuilder::createStringLitOp(mlir::Location loc, mlir::NamedAttribute sizeAttr(sizeTag, getI64IntegerAttr(data.size())); llvm::SmallVector attrs{dataAttr, sizeAttr}; return create(loc, llvm::ArrayRef{type}, - std::nullopt, attrs); + mlir::ValueRange{}, attrs); } mlir::Value fir::FirOpBuilder::genShape(mlir::Location loc, @@ -824,7 +824,7 @@ genNullPointerComparison(fir::FirOpBuilder &builder, mlir::Location loc, auto intPtrTy = builder.getIntPtrType(); auto ptrToInt = builder.createConvert(loc, intPtrTy, addr); auto c0 = builder.createIntegerConstant(loc, intPtrTy, 0); - return builder.create(loc, condition, ptrToInt, c0); + return mlir::arith::CmpIOp::create(builder, loc, condition, ptrToInt, c0); } mlir::Value fir::FirOpBuilder::genIsNotNullAddr(mlir::Location loc, @@ -1028,8 +1028,8 @@ fir::factory::readExtents(fir::FirOpBuilder &builder, mlir::Location loc, auto idxTy = builder.getIndexType(); for (decltype(rank) dim = 0; dim < rank; ++dim) { auto dimVal = builder.createIntegerConstant(loc, idxTy, dim); - auto dimInfo = builder.create(loc, idxTy, idxTy, idxTy, - box.getAddr(), dimVal); + auto dimInfo = fir::BoxDimsOp::create(builder, loc, idxTy, idxTy, idxTy, + box.getAddr(), dimVal); result.emplace_back(dimInfo.getResult(1)); } return result; @@ -1061,7 +1061,7 @@ fir::ExtendedValue fir::factory::readBoxValue(fir::FirOpBuilder &builder, assert(!box.hasAssumedRank() && "cannot read unlimited polymorphic or assumed rank fir.box"); auto addr = - builder.create(loc, box.getMemTy(), box.getAddr()); + fir::BoxAddrOp::create(builder, loc, box.getMemTy(), box.getAddr()); if (box.isCharacter()) { auto len = fir::factory::readCharLen(builder, loc, box); if (box.rank() == 0) @@ -1139,13 +1139,13 @@ static llvm::SmallVector getFromBox(mlir::Location loc, } else if (auto charTy = mlir::dyn_cast(eleTy)) { if (charTy.hasDynamicLen()) { auto idxTy = builder.getIndexType(); - auto eleSz = builder.create(loc, idxTy, boxVal); + auto eleSz = fir::BoxEleSizeOp::create(builder, loc, idxTy, boxVal); auto kindBytes = builder.getKindMap().getCharacterBitsize(charTy.getFKind()) / 8; mlir::Value charSz = builder.createIntegerConstant(loc, idxTy, kindBytes); mlir::Value len = - builder.create(loc, eleSz, charSz); + mlir::arith::DivSIOp::create(builder, loc, eleSz, charSz); return {len}; } } @@ -1237,11 +1237,11 @@ fir::ExtendedValue fir::factory::createStringLiteral(fir::FirOpBuilder &builder, loc, type, globalName, [&](fir::FirOpBuilder &builder) { auto stringLitOp = builder.createStringLitOp(loc, str); - builder.create(loc, stringLitOp); + fir::HasValueOp::create(builder, loc, stringLitOp); }, builder.createLinkOnceLinkage()); - auto addr = builder.create(loc, global.resultType(), - global.getSymbol()); + auto addr = fir::AddrOfOp::create(builder, loc, global.resultType(), + global.getSymbol()); auto len = builder.createIntegerConstant( loc, builder.getCharacterLengthType(), str.size()); return fir::CharBoxValue{addr, len}; @@ -1255,7 +1255,7 @@ fir::factory::createExtents(fir::FirOpBuilder &builder, mlir::Location loc, for (auto ext : seqTy.getShape()) extents.emplace_back( ext == fir::SequenceType::getUnknownExtent() - ? builder.create(loc, idxTy).getResult() + ? fir::UndefOp::create(builder, loc, idxTy).getResult() : builder.createIntegerConstant(loc, idxTy, ext)); return extents; } @@ -1396,11 +1396,11 @@ void fir::factory::genScalarAssignment(fir::FirOpBuilder &builder, assert(!fir::hasDynamicSize(type)); auto rhsVal = fir::getBase(rhs); if (fir::isa_ref_type(rhsVal.getType())) - rhsVal = builder.create(loc, rhsVal); + rhsVal = fir::LoadOp::create(builder, loc, rhsVal); mlir::Value lhsAddr = fir::getBase(lhs); rhsVal = builder.createConvert(loc, fir::unwrapRefType(lhsAddr.getType()), rhsVal); - builder.create(loc, rhsVal, lhsAddr); + fir::StoreOp::create(builder, loc, rhsVal, lhsAddr); } } @@ -1421,16 +1421,18 @@ static void genComponentByComponentAssignment(fir::FirOpBuilder &builder, auto &[lFieldName, lFieldTy] = lhsPair; auto &[rFieldName, rFieldTy] = rhsPair; assert(!fir::hasDynamicSize(lFieldTy) && !fir::hasDynamicSize(rFieldTy)); - mlir::Value rField = builder.create( - loc, fieldIndexType, rFieldName, rhsType, fir::getTypeParams(rhs)); + mlir::Value rField = + fir::FieldIndexOp::create(builder, loc, fieldIndexType, rFieldName, + rhsType, fir::getTypeParams(rhs)); auto rFieldRefType = builder.getRefType(rFieldTy); - mlir::Value fromCoor = builder.create( - loc, rFieldRefType, fir::getBase(rhs), rField); - mlir::Value field = builder.create( - loc, fieldIndexType, lFieldName, lhsType, fir::getTypeParams(lhs)); + mlir::Value fromCoor = fir::CoordinateOp::create( + builder, loc, rFieldRefType, fir::getBase(rhs), rField); + mlir::Value field = + fir::FieldIndexOp::create(builder, loc, fieldIndexType, lFieldName, + lhsType, fir::getTypeParams(lhs)); auto fieldRefType = builder.getRefType(lFieldTy); - mlir::Value toCoor = builder.create( - loc, fieldRefType, fir::getBase(lhs), field); + mlir::Value toCoor = fir::CoordinateOp::create(builder, loc, fieldRefType, + fir::getBase(lhs), field); std::optional outerLoop; if (auto sequenceType = mlir::dyn_cast(lFieldTy)) { // Create loops to assign array components elements by elements. @@ -1444,7 +1446,7 @@ static void genComponentByComponentAssignment(fir::FirOpBuilder &builder, for (auto extent : llvm::reverse(sequenceType.getShape())) { // TODO: add zero size test ! mlir::Value ub = builder.createIntegerConstant(loc, idxTy, extent - 1); - auto loop = builder.create(loc, zero, ub, one); + auto loop = fir::DoLoopOp::create(builder, loc, zero, ub, one); if (!outerLoop) outerLoop = loop; indices.push_back(loop.getInductionVar()); @@ -1453,19 +1455,19 @@ static void genComponentByComponentAssignment(fir::FirOpBuilder &builder, // Set indices in column-major order. std::reverse(indices.begin(), indices.end()); auto elementRefType = builder.getRefType(sequenceType.getEleTy()); - toCoor = builder.create(loc, elementRefType, toCoor, - indices); - fromCoor = builder.create(loc, elementRefType, - fromCoor, indices); + toCoor = fir::CoordinateOp::create(builder, loc, elementRefType, toCoor, + indices); + fromCoor = fir::CoordinateOp::create(builder, loc, elementRefType, + fromCoor, indices); } if (auto fieldEleTy = fir::unwrapSequenceType(lFieldTy); mlir::isa(fieldEleTy)) { assert(mlir::isa( mlir::cast(fieldEleTy).getEleTy()) && "allocatable members require deep copy"); - auto fromPointerValue = builder.create(loc, fromCoor); + auto fromPointerValue = fir::LoadOp::create(builder, loc, fromCoor); auto castTo = builder.createConvert(loc, fieldEleTy, fromPointerValue); - builder.create(loc, castTo, toCoor); + fir::StoreOp::create(builder, loc, castTo, toCoor); } else { auto from = fir::factory::componentToExtendedValue(builder, loc, fromCoor); @@ -1543,7 +1545,7 @@ void fir::factory::genRecordAssignment(fir::FirOpBuilder &builder, // runtime interface, but assume the fir.box is unchanged. // TODO: does this holds true with polymorphic entities ? auto toMutableBox = builder.createTemporary(loc, to.getType()); - builder.create(loc, to, toMutableBox); + fir::StoreOp::create(builder, loc, to, toMutableBox); if (isTemporaryLHS) fir::runtime::genAssignTemporary(builder, loc, toMutableBox, from); else @@ -1588,12 +1590,12 @@ mlir::Value fir::factory::genLenOfCharacter( auto idxTy = builder.getIndexType(); auto zero = builder.createIntegerConstant(loc, idxTy, 0); auto saturatedDiff = [&](mlir::Value lower, mlir::Value upper) { - auto diff = builder.create(loc, upper, lower); + auto diff = mlir::arith::SubIOp::create(builder, loc, upper, lower); auto one = builder.createIntegerConstant(loc, idxTy, 1); - auto size = builder.create(loc, diff, one); - auto cmp = builder.create( - loc, mlir::arith::CmpIPredicate::sgt, size, zero); - return builder.create(loc, cmp, size, zero); + auto size = mlir::arith::AddIOp::create(builder, loc, diff, one); + auto cmp = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::sgt, size, zero); + return mlir::arith::SelectOp::create(builder, loc, cmp, size, zero); }; if (substring.size() == 2) { auto upper = builder.createConvert(loc, idxTy, substring.back()); @@ -1615,7 +1617,7 @@ mlir::Value fir::factory::genLenOfCharacter( } if (fir::isa_box_type(memref.getType())) { if (mlir::isa(memref.getType())) - return builder.create(loc, idxTy, memref); + return fir::BoxCharLenOp::create(builder, loc, idxTy, memref); if (mlir::isa(memref.getType())) return CharacterExprHelper(builder, loc).readLengthFromBox(memref); fir::emitFatalError(loc, "memref has wrong type"); @@ -1684,10 +1686,10 @@ mlir::Value fir::factory::genMaxWithZero(fir::FirOpBuilder &builder, if (auto cst = mlir::dyn_cast(definingOp)) if (auto intAttr = mlir::dyn_cast(cst.getValue())) return intAttr.getInt() > 0 ? value : zero; - mlir::Value valueIsGreater = builder.create( - loc, mlir::arith::CmpIPredicate::sgt, value, zero); - return builder.create(loc, valueIsGreater, value, - zero); + mlir::Value valueIsGreater = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::sgt, value, zero); + return mlir::arith::SelectOp::create(builder, loc, valueIsGreater, value, + zero); } mlir::Value fir::factory::genMaxWithZero(fir::FirOpBuilder &builder, @@ -1703,8 +1705,8 @@ mlir::Value fir::factory::computeExtent(fir::FirOpBuilder &builder, mlir::Value one) { mlir::Type type = lb.getType(); // Let the folder deal with the common `ub - + 1` case. - auto diff = builder.create(loc, type, ub, lb); - auto rawExtent = builder.create(loc, type, diff, one); + auto diff = mlir::arith::SubIOp::create(builder, loc, type, ub, lb); + auto rawExtent = mlir::arith::AddIOp::create(builder, loc, type, diff, one); return fir::factory::genMaxWithZero(builder, loc, rawExtent, zero); } mlir::Value fir::factory::computeExtent(fir::FirOpBuilder &builder, @@ -1724,8 +1726,8 @@ genCPtrOrCFunptrFieldIndex(fir::FirOpBuilder &builder, mlir::Location loc, auto addrFieldName = recTy.getTypeList()[0].first; mlir::Type addrFieldTy = recTy.getTypeList()[0].second; auto fieldIndexType = fir::FieldType::get(cptrTy.getContext()); - mlir::Value addrFieldIndex = builder.create( - loc, fieldIndexType, addrFieldName, recTy, + mlir::Value addrFieldIndex = fir::FieldIndexOp::create( + builder, loc, fieldIndexType, addrFieldName, recTy, /*typeParams=*/mlir::ValueRange{}); return {addrFieldIndex, addrFieldTy}; } @@ -1736,8 +1738,8 @@ mlir::Value fir::factory::genCPtrOrCFunptrAddr(fir::FirOpBuilder &builder, mlir::Type ty) { auto [addrFieldIndex, addrFieldTy] = genCPtrOrCFunptrFieldIndex(builder, loc, ty); - return builder.create(loc, builder.getRefType(addrFieldTy), - cPtr, addrFieldIndex); + return fir::CoordinateOp::create( + builder, loc, builder.getRefType(addrFieldTy), cPtr, addrFieldIndex); } mlir::Value fir::factory::genCDevPtrAddr(fir::FirOpBuilder &builder, @@ -1748,15 +1750,15 @@ mlir::Value fir::factory::genCDevPtrAddr(fir::FirOpBuilder &builder, auto cptrFieldName = recTy.getTypeList()[0].first; mlir::Type cptrFieldTy = recTy.getTypeList()[0].second; auto fieldIndexType = fir::FieldType::get(ty.getContext()); - mlir::Value cptrFieldIndex = builder.create( - loc, fieldIndexType, cptrFieldName, recTy, + mlir::Value cptrFieldIndex = fir::FieldIndexOp::create( + builder, loc, fieldIndexType, cptrFieldName, recTy, /*typeParams=*/mlir::ValueRange{}); - auto cptrCoord = builder.create( - loc, builder.getRefType(cptrFieldTy), cDevPtr, cptrFieldIndex); + auto cptrCoord = fir::CoordinateOp::create( + builder, loc, builder.getRefType(cptrFieldTy), cDevPtr, cptrFieldIndex); auto [addrFieldIndex, addrFieldTy] = genCPtrOrCFunptrFieldIndex(builder, loc, cptrFieldTy); - return builder.create(loc, builder.getRefType(addrFieldTy), - cptrCoord, addrFieldIndex); + return fir::CoordinateOp::create( + builder, loc, builder.getRefType(addrFieldTy), cptrCoord, addrFieldIndex); } mlir::Value fir::factory::genCPtrOrCFunptrValue(fir::FirOpBuilder &builder, @@ -1769,13 +1771,13 @@ mlir::Value fir::factory::genCPtrOrCFunptrValue(fir::FirOpBuilder &builder, genCPtrOrCFunptrFieldIndex(builder, loc, cPtrTy); mlir::Value cPtrCoor; if (fir::isa_ref_type(cPtr.getType())) { - cPtrCoor = builder.create( - loc, builder.getRefType(addrFieldTy), cPtr, addrFieldIndex); + cPtrCoor = fir::CoordinateOp::create( + builder, loc, builder.getRefType(addrFieldTy), cPtr, addrFieldIndex); } else { auto arrayAttr = builder.getArrayAttr( {builder.getIntegerAttr(builder.getIndexType(), 0)}); - cPtrCoor = builder.create(loc, addrFieldTy, cPtr, - arrayAttr); + cPtrCoor = fir::ExtractValueOp::create(builder, loc, addrFieldTy, cPtr, + arrayAttr); } return genCPtrOrCFunptrValue(builder, loc, cPtrCoor); } @@ -1783,13 +1785,14 @@ mlir::Value fir::factory::genCPtrOrCFunptrValue(fir::FirOpBuilder &builder, if (fir::isa_ref_type(cPtr.getType())) { mlir::Value cPtrAddr = fir::factory::genCPtrOrCFunptrAddr(builder, loc, cPtr, cPtrTy); - return builder.create(loc, cPtrAddr); + return fir::LoadOp::create(builder, loc, cPtrAddr); } auto [addrFieldIndex, addrFieldTy] = genCPtrOrCFunptrFieldIndex(builder, loc, cPtrTy); auto arrayAttr = builder.getArrayAttr({builder.getIntegerAttr(builder.getIndexType(), 0)}); - return builder.create(loc, addrFieldTy, cPtr, arrayAttr); + return fir::ExtractValueOp::create(builder, loc, addrFieldTy, cPtr, + arrayAttr); } fir::BoxValue fir::factory::createBoxValue(fir::FirOpBuilder &builder, @@ -1837,8 +1840,8 @@ mlir::Value fir::factory::createNullBoxProc(fir::FirOpBuilder &builder, if (!boxTy) fir::emitFatalError(loc, "Procedure pointer must be of BoxProcType"); auto boxEleTy{fir::unwrapRefType(boxTy.getEleTy())}; - mlir::Value initVal{builder.create(loc, boxEleTy)}; - return builder.create(loc, boxTy, initVal); + mlir::Value initVal{fir::ZeroOp::create(builder, loc, boxEleTy)}; + return fir::EmboxProcOp::create(builder, loc, boxTy, initVal); } void fir::factory::setInternalLinkage(mlir::func::FuncOp func) { @@ -1897,15 +1900,15 @@ llvm::SmallVector fir::factory::updateRuntimeExtentsForEmptyArrays( mlir::Type type = extent.getType(); mlir::Value zero = createZeroValue(builder, loc, type); zeroes.push_back(zero); - mlir::Value isZero = builder.create( - loc, mlir::arith::CmpIPredicate::eq, extent, zero); - isEmpty = builder.create(loc, isEmpty, isZero); + mlir::Value isZero = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, extent, zero); + isEmpty = mlir::arith::OrIOp::create(builder, loc, isEmpty, isZero); } llvm::SmallVector newExtents; for (auto [zero, extent] : llvm::zip_equal(zeroes, extents)) { newExtents.push_back( - builder.create(loc, isEmpty, zero, extent)); + mlir::arith::SelectOp::create(builder, loc, isEmpty, zero, extent)); } return newExtents; } @@ -1926,7 +1929,7 @@ void fir::factory::genDimInfoFromBox( for (unsigned i = 0; i < rank; ++i) { mlir::Value dim = builder.createIntegerConstant(loc, idxTy, i); auto dimInfo = - builder.create(loc, idxTy, idxTy, idxTy, box, dim); + fir::BoxDimsOp::create(builder, loc, idxTy, idxTy, idxTy, box, dim); if (lbounds) lbounds->push_back(dimInfo.getLowerBound()); if (extents) @@ -1943,12 +1946,12 @@ mlir::Value fir::factory::genLifetimeStart(mlir::OpBuilder &builder, mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get( alloc.getContext(), getAllocaAddressSpace(dl)); mlir::Value cast = - builder.create(loc, ptrTy, alloc.getResult()); - builder.create(loc, size, cast); + fir::ConvertOp::create(builder, loc, ptrTy, alloc.getResult()); + mlir::LLVM::LifetimeStartOp::create(builder, loc, size, cast); return cast; } void fir::factory::genLifetimeEnd(mlir::OpBuilder &builder, mlir::Location loc, mlir::Value cast, int64_t size) { - builder.create(loc, size, cast); + mlir::LLVM::LifetimeEndOp::create(builder, loc, size, cast); } diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp index e59a6bf2bf224..c3948f2caf67b 100644 --- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp +++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp @@ -50,7 +50,7 @@ hlfir::getExplicitExtentsFromShape(mlir::Value shape, int64_t extent = exprShape[i]; mlir::Value extentVal; if (extent == expr.getUnknownExtent()) { - auto op = builder.create(shape.getLoc(), shape, i); + auto op = hlfir::GetExtentOp::create(builder, shape.getLoc(), shape, i); extentVal = op.getResult(); } else { extentVal = @@ -150,7 +150,7 @@ static mlir::Value genCharacterVariableLength(mlir::Location loc, return builder.createIntegerConstant(loc, builder.getIndexType(), charType.getLen()); if (var.isMutableBox()) - var = hlfir::Entity{builder.create(loc, var)}; + var = hlfir::Entity{fir::LoadOp::create(builder, loc, var)}; mlir::Value len = fir::factory::CharacterExprHelper{builder, loc}.getLength( var.getFirBase()); assert(len && "failed to retrieve length"); @@ -164,8 +164,8 @@ static fir::CharBoxValue genUnboxChar(mlir::Location loc, return {emboxChar.getMemref(), emboxChar.getLen()}; mlir::Type refType = fir::ReferenceType::get( mlir::cast(boxChar.getType()).getEleTy()); - auto unboxed = builder.create( - loc, refType, builder.getIndexType(), boxChar); + auto unboxed = fir::UnboxCharOp::create(builder, loc, refType, + builder.getIndexType(), boxChar); mlir::Value addr = unboxed.getResult(0); mlir::Value len = unboxed.getResult(1); if (auto varIface = boxChar.getDefiningOp()) @@ -278,8 +278,9 @@ hlfir::genDeclare(mlir::Location loc, fir::FirOpBuilder &builder, box.nonDeferredLenParams().end()); }, [](const auto &) {}); - auto declareOp = builder.create( - loc, base, name, shapeOrShift, lenParams, dummyScope, flags, dataAttr); + auto declareOp = + hlfir::DeclareOp::create(builder, loc, base, name, shapeOrShift, + lenParams, dummyScope, flags, dataAttr); return mlir::cast(declareOp.getOperation()); } @@ -312,12 +313,12 @@ hlfir::genAssociateExpr(mlir::Location loc, fir::FirOpBuilder &builder, genLengthParameters(loc, builder, value, lenParams); if (attr) { assert(name.empty() && "It attribute is provided, no-name is expected"); - return builder.create(loc, source, shape, lenParams, - fir::FortranVariableFlagsAttr{}, - llvm::ArrayRef{*attr}); + return hlfir::AssociateOp::create(builder, loc, source, shape, lenParams, + fir::FortranVariableFlagsAttr{}, + llvm::ArrayRef{*attr}); } - return builder.create(loc, source, name, shape, lenParams, - fir::FortranVariableFlagsAttr{}); + return hlfir::AssociateOp::create(builder, loc, source, name, shape, + lenParams, fir::FortranVariableFlagsAttr{}); } mlir::Value hlfir::genVariableRawAddress(mlir::Location loc, @@ -326,12 +327,12 @@ mlir::Value hlfir::genVariableRawAddress(mlir::Location loc, assert(var.isVariable() && "only address of variables can be taken"); mlir::Value baseAddr = var.getFirBase(); if (var.isMutableBox()) - baseAddr = builder.create(loc, baseAddr); + baseAddr = fir::LoadOp::create(builder, loc, baseAddr); // Get raw address. if (mlir::isa(var.getType())) baseAddr = genUnboxChar(loc, builder, var.getBase()).getAddr(); if (mlir::isa(baseAddr.getType())) - baseAddr = builder.create(loc, baseAddr); + baseAddr = fir::BoxAddrOp::create(builder, loc, baseAddr); return baseAddr; } @@ -350,8 +351,8 @@ mlir::Value hlfir::genVariableBoxChar(mlir::Location loc, fir::BoxCharType::get(builder.getContext(), charType.getFKind()); auto scalarAddr = builder.createConvert(loc, fir::ReferenceType::get(charType), addr); - return builder.create(loc, boxCharType, scalarAddr, - lengths[0]); + return fir::EmboxCharOp::create(builder, loc, boxCharType, scalarAddr, + lengths[0]); } static hlfir::Entity changeBoxAttributes(mlir::Location loc, @@ -365,8 +366,8 @@ static hlfir::Entity changeBoxAttributes(mlir::Location loc, getNonDefaultLowerBounds(loc, builder, var); if (!lbounds.empty()) shift = builder.genShift(loc, lbounds); - auto rebox = builder.create(loc, forceBoxType, var, shift, - /*slice=*/nullptr); + auto rebox = fir::ReboxOp::create(builder, loc, forceBoxType, var, shift, + /*slice=*/nullptr); return hlfir::Entity{rebox}; } @@ -404,9 +405,8 @@ hlfir::Entity hlfir::genVariableBox(mlir::Location loc, fir::ReferenceType::get(fir::unwrapRefType(forceBoxType.getEleTy())); addr = builder.createConvert(loc, baseType, addr); } - auto embox = - builder.create(loc, boxType, addr, shape, - /*slice=*/mlir::Value{}, typeParams); + auto embox = fir::EmboxOp::create(builder, loc, boxType, addr, shape, + /*slice=*/mlir::Value{}, typeParams); return hlfir::Entity{embox.getResult()}; } @@ -416,7 +416,7 @@ hlfir::Entity hlfir::loadTrivialScalar(mlir::Location loc, entity = derefPointersAndAllocatables(loc, builder, entity); if (entity.isVariable() && entity.isScalar() && fir::isa_trivial(entity.getFortranElementType())) { - return Entity{builder.create(loc, entity)}; + return Entity{fir::LoadOp::create(builder, loc, entity)}; } return entity; } @@ -429,8 +429,8 @@ hlfir::Entity hlfir::getElementAt(mlir::Location loc, llvm::SmallVector lenParams; genLengthParameters(loc, builder, entity, lenParams); if (mlir::isa(entity.getType())) - return hlfir::Entity{builder.create( - loc, entity, oneBasedIndices, lenParams)}; + return hlfir::Entity{hlfir::ApplyOp::create(builder, loc, entity, + oneBasedIndices, lenParams)}; // Build hlfir.designate. The lower bounds may need to be added to // the oneBasedIndices since hlfir.designate expect indices // based on the array operand lower bounds. @@ -445,16 +445,16 @@ hlfir::Entity hlfir::getElementAt(mlir::Location loc, for (auto [oneBased, lb] : llvm::zip(oneBasedIndices, lbounds)) { auto lbIdx = builder.createConvert(loc, idxTy, lb); auto oneBasedIdx = builder.createConvert(loc, idxTy, oneBased); - auto shift = builder.create(loc, lbIdx, one); + auto shift = mlir::arith::SubIOp::create(builder, loc, lbIdx, one); mlir::Value index = - builder.create(loc, oneBasedIdx, shift); + mlir::arith::AddIOp::create(builder, loc, oneBasedIdx, shift); indices.push_back(index); } - designate = builder.create(loc, resultType, entity, - indices, lenParams); + designate = hlfir::DesignateOp::create(builder, loc, resultType, entity, + indices, lenParams); } else { - designate = builder.create(loc, resultType, entity, - oneBasedIndices, lenParams); + designate = hlfir::DesignateOp::create(builder, loc, resultType, entity, + oneBasedIndices, lenParams); } return mlir::cast(designate.getOperation()); } @@ -467,8 +467,8 @@ static mlir::Value genUBound(mlir::Location loc, fir::FirOpBuilder &builder, return extent; extent = builder.createConvert(loc, one.getType(), extent); lb = builder.createConvert(loc, one.getType(), lb); - auto add = builder.create(loc, lb, extent); - return builder.create(loc, add, one); + auto add = mlir::arith::AddIOp::create(builder, loc, lb, extent); + return mlir::arith::SubIOp::create(builder, loc, add, one); } llvm::SmallVector> @@ -557,8 +557,8 @@ static mlir::Value computeVariableExtent(mlir::Location loc, assert(mlir::isa(variable.getType()) && "array variable with dynamic extent must be boxed"); mlir::Value dimVal = builder.createIntegerConstant(loc, idxTy, dim); - auto dimInfo = builder.create(loc, idxTy, idxTy, idxTy, - variable, dimVal); + auto dimInfo = fir::BoxDimsOp::create(builder, loc, idxTy, idxTy, idxTy, + variable, dimVal); return dimInfo.getExtent(); } llvm::SmallVector getVariableExtents(mlir::Location loc, @@ -608,14 +608,14 @@ mlir::Value hlfir::genShape(mlir::Location loc, fir::FirOpBuilder &builder, return shape; if (mlir::isa(shape.getType())) if (auto s = shape.getDefiningOp()) - return builder.create(loc, s.getExtents()); + return fir::ShapeOp::create(builder, loc, s.getExtents()); } if (mlir::isa(entity.getType())) - return builder.create(loc, entity.getBase()); + return hlfir::ShapeOfOp::create(builder, loc, entity.getBase()); // There is no shape lying around for this entity. Retrieve the extents and // build a new fir.shape. - return builder.create(loc, - getVariableExtents(loc, builder, entity)); + return fir::ShapeOp::create(builder, loc, + getVariableExtents(loc, builder, entity)); } llvm::SmallVector @@ -668,7 +668,7 @@ mlir::Value hlfir::genLBound(mlir::Location loc, fir::FirOpBuilder &builder, mlir::Type idxTy = builder.getIndexType(); mlir::Value dimVal = builder.createIntegerConstant(loc, idxTy, dim); auto dimInfo = - builder.create(loc, idxTy, idxTy, idxTy, entity, dimVal); + fir::BoxDimsOp::create(builder, loc, idxTy, idxTy, idxTy, entity, dimVal); return dimInfo.getLowerBound(); } @@ -708,7 +708,7 @@ void hlfir::genLengthParameters(mlir::Location loc, fir::FirOpBuilder &builder, return; } if (entity.isCharacter()) { - result.push_back(builder.create(loc, expr)); + result.push_back(hlfir::GetLengthOp::create(builder, loc, expr)); return; } TODO(loc, "inquire PDTs length parameters of hlfir.expr"); @@ -735,7 +735,7 @@ mlir::Value hlfir::genRank(mlir::Location loc, fir::FirOpBuilder &builder, return builder.createIntegerConstant(loc, resultType, entity.getRank()); assert(entity.isBoxAddressOrValue() && "assumed-ranks are box addresses or values"); - return builder.create(loc, resultType, entity); + return fir::BoxRankOp::create(builder, loc, resultType, entity); } // Return a "shape" that can be used in fir.embox/fir.rebox with \p exv base. @@ -796,20 +796,20 @@ hlfir::Entity hlfir::derefPointersAndAllocatables(mlir::Location loc, fir::FirOpBuilder &builder, Entity entity) { if (entity.isMutableBox()) { - hlfir::Entity boxLoad{builder.create(loc, entity)}; + hlfir::Entity boxLoad{fir::LoadOp::create(builder, loc, entity)}; if (entity.isScalar()) { if (!entity.isPolymorphic() && !entity.hasLengthParameters()) - return hlfir::Entity{builder.create(loc, boxLoad)}; + return hlfir::Entity{fir::BoxAddrOp::create(builder, loc, boxLoad)}; mlir::Type elementType = boxLoad.getFortranElementType(); if (auto charType = mlir::dyn_cast(elementType)) { - mlir::Value base = builder.create(loc, boxLoad); + mlir::Value base = fir::BoxAddrOp::create(builder, loc, boxLoad); if (charType.hasConstantLen()) return hlfir::Entity{base}; mlir::Value len = genCharacterVariableLength(loc, builder, entity); auto boxCharType = fir::BoxCharType::get(builder.getContext(), charType.getFKind()); return hlfir::Entity{ - builder.create(loc, boxCharType, base, len) + fir::EmboxCharOp::create(builder, loc, boxCharType, base, len) .getResult()}; } } @@ -819,7 +819,7 @@ hlfir::Entity hlfir::derefPointersAndAllocatables(mlir::Location loc, // information. Keep them boxed. return boxLoad; } else if (entity.isProcedurePointer()) { - return hlfir::Entity{builder.create(loc, entity)}; + return hlfir::Entity{fir::LoadOp::create(builder, loc, entity)}; } return entity; } @@ -870,8 +870,8 @@ hlfir::ElementalOp hlfir::genElementalOp( mlir::Value polymorphicMold, mlir::Type exprType) { if (!exprType) exprType = getArrayExprType(elementType, shape, !!polymorphicMold); - auto elementalOp = builder.create( - loc, exprType, shape, polymorphicMold, typeParams, isUnordered); + auto elementalOp = hlfir::ElementalOp::create( + builder, loc, exprType, shape, polymorphicMold, typeParams, isUnordered); auto insertPt = builder.saveInsertionPoint(); builder.setInsertionPointToStart(elementalOp.getBody()); mlir::Value elementResult = genKernel(loc, builder, elementalOp.getIndices()); @@ -881,7 +881,7 @@ hlfir::ElementalOp hlfir::genElementalOp( // here. if (fir::isa_trivial(elementResult.getType())) elementResult = builder.createConvert(loc, elementType, elementResult); - builder.create(loc, elementResult); + hlfir::YieldElementOp::create(builder, loc, elementResult); builder.restoreInsertionPoint(insertPt); return elementalOp; } @@ -948,10 +948,10 @@ hlfir::LoopNest hlfir::genLoopNest(mlir::Location loc, 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); + auto one = mlir::arith::ConstantIndexOp::create(builder, loc, 1); mlir::Type indexType = builder.getIndexType(); if (emitWorkshareLoop) { - auto wslw = builder.create(loc); + auto wslw = mlir::omp::WorkshareLoopWrapperOp::create(builder, loc); loopNest.outerOp = wslw; builder.createBlock(&wslw.getRegion()); mlir::omp::LoopNestOperands lnops; @@ -961,12 +961,12 @@ hlfir::LoopNest hlfir::genLoopNest(mlir::Location loc, lnops.loopUpperBounds.push_back(extent); lnops.loopSteps.push_back(one); } - auto lnOp = builder.create(loc, lnops); + auto lnOp = mlir::omp::LoopNestOp::create(builder, 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); + mlir::omp::YieldOp::create(builder, loc); for (unsigned dim = 0; dim < extents.size(); dim++) loopNest.oneBasedIndices[extents.size() - dim - 1] = lnOp.getRegion().front().getArgument(dim); @@ -975,7 +975,7 @@ hlfir::LoopNest hlfir::genLoopNest(mlir::Location loc, for (auto extent : llvm::reverse(extents)) { auto ub = builder.createConvert(loc, indexType, extent); auto doLoop = - builder.create(loc, one, ub, one, isUnordered); + fir::DoLoopOp::create(builder, loc, one, ub, one, isUnordered); if (!couldVectorize) { mlir::LLVM::LoopVectorizeAttr va{mlir::LLVM::LoopVectorizeAttr::get( builder.getContext(), @@ -1002,7 +1002,7 @@ llvm::SmallVector hlfir::genLoopNestWithReductions( bool isUnordered) { assert(!extents.empty() && "must have at least one extent"); // Build loop nest from column to row. - auto one = builder.create(loc, 1); + auto one = mlir::arith::ConstantIndexOp::create(builder, loc, 1); mlir::Type indexType = builder.getIndexType(); unsigned dim = extents.size() - 1; fir::DoLoopOp outerLoop = nullptr; @@ -1018,16 +1018,15 @@ llvm::SmallVector hlfir::genLoopNestWithReductions( // of its parent loop. fir::DoLoopOp doLoop; if (!parentLoop) { - doLoop = builder.create(loc, one, ub, one, isUnordered, - /*finalCountValue=*/false, - reductionInits); + doLoop = fir::DoLoopOp::create(builder, loc, one, ub, one, isUnordered, + /*finalCountValue=*/false, reductionInits); } else { - doLoop = builder.create(loc, one, ub, one, isUnordered, - /*finalCountValue=*/false, - parentLoop.getRegionIterArgs()); + doLoop = fir::DoLoopOp::create(builder, loc, one, ub, one, isUnordered, + /*finalCountValue=*/false, + parentLoop.getRegionIterArgs()); if (!reductionInits.empty()) { // Return the results of the child loop from its parent loop. - builder.create(loc, doLoop.getResults()); + fir::ResultOp::create(builder, loc, doLoop.getResults()); } } @@ -1044,7 +1043,7 @@ llvm::SmallVector hlfir::genLoopNestWithReductions( genBody(loc, builder, oneBasedIndices, parentLoop.getRegionIterArgs()); builder.setInsertionPointToEnd(parentLoop.getBody()); if (!reductionValues.empty()) - builder.create(loc, reductionValues); + fir::ResultOp::create(builder, loc, reductionValues); builder.setInsertionPointAfter(outerLoop); return outerLoop->getResults(); } @@ -1057,18 +1056,18 @@ conditionallyEvaluate(mlir::Location loc, fir::FirOpBuilder &builder, // Evaluate in some region that will be moved into the actual ifOp (the actual // ifOp can only be created when the result types are known). - auto badIfOp = builder.create(loc, condition.getType(), condition, - /*withElseRegion=*/false); + auto badIfOp = fir::IfOp::create(builder, loc, condition.getType(), condition, + /*withElseRegion=*/false); mlir::Block *preparationBlock = &badIfOp.getThenRegion().front(); builder.setInsertionPointToStart(preparationBlock); fir::ExtendedValue result = genIfTrue(); fir::ResultOp resultOp = result.match( [&](const fir::CharBoxValue &box) -> fir::ResultOp { - return builder.create( - loc, mlir::ValueRange{box.getAddr(), box.getLen()}); + return fir::ResultOp::create( + builder, loc, mlir::ValueRange{box.getAddr(), box.getLen()}); }, [&](const mlir::Value &addr) -> fir::ResultOp { - return builder.create(loc, addr); + return fir::ResultOp::create(builder, loc, addr); }, [&](const auto &) -> fir::ResultOp { TODO(loc, "unboxing non scalar optional fir.box"); @@ -1077,8 +1076,8 @@ conditionallyEvaluate(mlir::Location loc, fir::FirOpBuilder &builder, // Create actual fir.if operation. auto ifOp = - builder.create(loc, resultOp->getOperandTypes(), condition, - /*withElseRegion=*/true); + fir::IfOp::create(builder, loc, resultOp->getOperandTypes(), condition, + /*withElseRegion=*/true); // Move evaluation into Then block, preparationBlock->moveBefore(&ifOp.getThenRegion().back()); ifOp.getThenRegion().back().erase(); @@ -1087,11 +1086,11 @@ conditionallyEvaluate(mlir::Location loc, fir::FirOpBuilder &builder, llvm::SmallVector absentValues; for (mlir::Type resTy : ifOp->getResultTypes()) { if (fir::isa_ref_type(resTy) || fir::isa_box_type(resTy)) - absentValues.emplace_back(builder.create(loc, resTy)); + absentValues.emplace_back(fir::AbsentOp::create(builder, loc, resTy)); else - absentValues.emplace_back(builder.create(loc, resTy)); + absentValues.emplace_back(fir::ZeroOp::create(builder, loc, resTy)); } - builder.create(loc, absentValues); + fir::ResultOp::create(builder, loc, absentValues); badIfOp->erase(); // Build fir::ExtendedValue from the result values. @@ -1139,8 +1138,8 @@ static fir::ExtendedValue translateVariableToExtendedValue( } if (variable.mayBeOptional()) { if (!keepScalarOptionalBoxed && variable.isScalar()) { - mlir::Value isPresent = builder.create( - loc, builder.getI1Type(), variable); + mlir::Value isPresent = fir::IsPresentOp::create( + builder, loc, builder.getI1Type(), variable); return conditionallyEvaluate( loc, builder, isPresent, [&]() -> fir::ExtendedValue { mlir::Value base = genVariableRawAddress(loc, builder, variable); @@ -1249,7 +1248,7 @@ static fir::ExtendedValue placeTrivialInMemory(mlir::Location loc, if (targetType != val.getType()) builder.createStoreWithConvert(loc, val, temp); else - builder.create(loc, val, temp); + fir::StoreOp::create(builder, loc, val, temp); return temp; } @@ -1369,8 +1368,8 @@ hlfir::createTempFromMold(mlir::Location loc, fir::FirOpBuilder &builder, llvm::ArrayRef typeParams, fir::FortranVariableFlagsAttr attrs) -> mlir::Value { auto declareOp = - builder.create(loc, memref, name, shape, typeParams, - /*dummy_scope=*/nullptr, attrs); + hlfir::DeclareOp::create(builder, loc, memref, name, shape, typeParams, + /*dummy_scope=*/nullptr, attrs); return declareOp.getBase(); }; @@ -1403,11 +1402,11 @@ hlfir::Entity hlfir::createStackTempFromMold(mlir::Location loc, builder.createTemporary(loc, sequenceType, tmpName, extents, lenParams); } else { alloc = builder.createTemporary(loc, mold.getFortranElementType(), tmpName, - /*shape=*/std::nullopt, lenParams); + /*shape=*/{}, lenParams); } auto declareOp = - builder.create(loc, alloc, tmpName, shape, lenParams, - /*dummy_scope=*/nullptr, declAttrs); + hlfir::DeclareOp::create(builder, loc, alloc, tmpName, shape, lenParams, + /*dummy_scope=*/nullptr, declAttrs); return hlfir::Entity{declareOp.getBase()}; } @@ -1422,8 +1421,8 @@ hlfir::convertCharacterKind(mlir::Location loc, fir::FirOpBuilder &builder, if (src.second.has_value()) src.second.value()(); - return hlfir::EntityWithAttributes{builder.create( - loc, res.getAddr(), ".temp.kindconvert", /*shape=*/nullptr, + return hlfir::EntityWithAttributes{hlfir::DeclareOp::create( + builder, loc, res.getAddr(), ".temp.kindconvert", /*shape=*/nullptr, /*typeparams=*/mlir::ValueRange{res.getLen()}, /*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{})}; } @@ -1494,10 +1493,10 @@ hlfir::genTypeAndKindConvert(mlir::Location loc, fir::FirOpBuilder &builder, } auto shapeShiftType = fir::ShapeShiftType::get(builder.getContext(), rank); mlir::Value shapeShift = - builder.create(loc, shapeShiftType, lbAndExtents); - auto declareOp = builder.create( - loc, associate.getFirBase(), *associate.getUniqName(), shapeShift, - associate.getTypeparams(), /*dummy_scope=*/nullptr, + fir::ShapeShiftOp::create(builder, loc, shapeShiftType, lbAndExtents); + auto declareOp = hlfir::DeclareOp::create( + builder, loc, associate.getFirBase(), *associate.getUniqName(), + shapeShift, associate.getTypeparams(), /*dummy_scope=*/nullptr, /*flags=*/fir::FortranVariableFlagsAttr{}); hlfir::Entity castWithLbounds = mlir::cast(declareOp.getOperation()); @@ -1536,8 +1535,8 @@ std::pair hlfir::computeEvaluateOpInNewTemp( extents, typeParams); mlir::Value innerMemory = evalInMem.getMemory(); temp = builder.createConvert(loc, innerMemory.getType(), temp); - auto declareOp = builder.create( - loc, temp, tmpName, shape, typeParams, + auto declareOp = hlfir::DeclareOp::create( + builder, loc, temp, tmpName, shape, typeParams, /*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{}); computeEvaluateOpIn(loc, builder, evalInMem, declareOp.getOriginalBase()); return {hlfir::Entity{declareOp.getBase()}, /*heapAllocated=*/heapAllocated}; @@ -1601,7 +1600,7 @@ hlfir::Entity hlfir::gen1DSection(mlir::Location loc, } } mlir::Value sectionShape = - builder.create(loc, extents[dim - 1]); + fir::ShapeOp::create(builder, loc, extents[dim - 1]); // The result type is one of: // !fir.box/class> @@ -1617,9 +1616,9 @@ hlfir::Entity hlfir::gen1DSection(mlir::Location loc, fir::SequenceType::get({dimExtent}, seqType.getEleTy()); sectionType = fir::wrapInClassOrBoxType(sectionType, array.isPolymorphic()); - auto designate = builder.create( - loc, sectionType, array, /*component=*/"", /*componentShape=*/nullptr, - subscripts, + auto designate = hlfir::DesignateOp::create( + builder, loc, sectionType, array, /*component=*/"", + /*componentShape=*/nullptr, subscripts, /*substring=*/mlir::ValueRange{}, /*complexPartAttr=*/std::nullopt, sectionShape, typeParams); return hlfir::Entity{designate.getResult()}; diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index d32c1fde59f27..b589a6c7c62fb 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -385,13 +385,18 @@ static constexpr IntrinsicHandler handlers[]{ &I::genChdir, {{{"name", asAddr}, {"status", asAddr, handleDynamicOptional}}}, /*isElemental=*/false}, - {"clock64", &I::genClock64, {}, /*isElemental=*/false}, + {"clock", &I::genNVVMTime, {}, /*isElemental=*/false}, + {"clock64", + &I::genNVVMTime, + {}, + /*isElemental=*/false}, {"cmplx", &I::genCmplx, {{{"x", asValue}, {"y", asValue, handleDynamicOptional}}}}, {"command_argument_count", &I::genCommandArgumentCount}, {"conjg", &I::genConjg}, {"cosd", &I::genCosd}, + {"cospi", &I::genCospi}, {"count", &I::genCount, {{{"mask", asAddr}, {"dim", asValue}, {"kind", asValue}}}, @@ -503,6 +508,10 @@ static constexpr IntrinsicHandler handlers[]{ {"getgid", &I::genGetGID}, {"getpid", &I::genGetPID}, {"getuid", &I::genGetUID}, + {"globaltimer", + &I::genNVVMTime, + {}, + /*isElemental=*/false}, {"hostnm", &I::genHostnm, {{{"c", asBox}, {"status", asAddr, handleDynamicOptional}}}, @@ -892,6 +901,7 @@ static constexpr IntrinsicHandler handlers[]{ {{{"number", asValue}, {"handler", asAddr}, {"status", asAddr}}}, /*isElemental=*/false}, {"sind", &I::genSind}, + {"sinpi", &I::genSinpi}, {"size", &I::genSize, {{{"array", asBox}, @@ -1101,7 +1111,7 @@ mlir::Value genLibCall(fir::FirOpBuilder &builder, mlir::Location loc, // was just created from user functions with the same name. funcOp->setAttr(fir::FIROpsDialect::getFirRuntimeAttrName(), builder.getUnitAttr()); - auto libCall = builder.create(loc, funcOp, args); + auto libCall = fir::CallOp::create(builder, loc, funcOp, args); // TODO: ensure 'strictfp' setting on the call for "precise/strict" // FP mode. Set appropriate Fast-Math Flags otherwise. // TODO: we should also mark as many libm function as possible @@ -1115,7 +1125,7 @@ mlir::Value genLibCall(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type soughtFuncType = funcOp.getFunctionType(); if (soughtFuncType == libFuncType) { - libCall = builder.create(loc, funcOp, args); + libCall = fir::CallOp::create(builder, loc, funcOp, args); } else { // A function with the same name might have been declared // before (e.g. with an explicit interface and a binding label). @@ -1129,13 +1139,13 @@ mlir::Value genLibCall(fir::FirOpBuilder &builder, mlir::Location loc, llvm::Twine("' may lead to undefined behavior."))); mlir::SymbolRefAttr funcSymbolAttr = builder.getSymbolRefAttr(libFuncName); mlir::Value funcPointer = - builder.create(loc, soughtFuncType, funcSymbolAttr); + fir::AddrOfOp::create(builder, loc, soughtFuncType, funcSymbolAttr); funcPointer = builder.createConvert(loc, libFuncType, funcPointer); llvm::SmallVector operands{funcPointer}; operands.append(args.begin(), args.end()); - libCall = builder.create(loc, mlir::SymbolRefAttr{}, - libFuncType.getResults(), operands); + libCall = fir::CallOp::create(builder, loc, mlir::SymbolRefAttr{}, + libFuncType.getResults(), operands); } LLVM_DEBUG(libCall.dump(); llvm::dbgs() << "\n"); @@ -1211,7 +1221,7 @@ mlir::Value genMathOp(fir::FirOpBuilder &builder, mlir::Location loc, LLVM_DEBUG(llvm::dbgs() << "Generating '" << mathLibFuncName << "' operation with type "; mathLibFuncType.dump(); llvm::dbgs() << "\n"); - result = builder.create(loc, args); + result = T::create(builder, loc, args); } LLVM_DEBUG(result.dump(); llvm::dbgs() << "\n"); return result; @@ -1231,8 +1241,11 @@ mlir::Value genComplexMathOp(fir::FirOpBuilder &builder, mlir::Location loc, llvm::StringRef mathLibFuncName = mathOp.runtimeFunc; if (!mathLibFuncName.empty()) { // If we enabled MLIR complex or can use approximate operations, we should - // NOT use libm. - if (!forceMlirComplex && !canUseApprox) { + // NOT use libm. Avoid libm when targeting AMDGPU as those symbols are not + // available on the device and we rely on MLIR complex operations to + // later map to OCML calls. + bool isAMDGPU = fir::getTargetTriple(builder.getModule()).isAMDGCN(); + if (!forceMlirComplex && !canUseApprox && !isAMDGPU) { result = genLibCall(builder, loc, mathOp, mathLibFuncType, args); LLVM_DEBUG(result.dump(); llvm::dbgs() << "\n"); return result; @@ -1246,12 +1259,12 @@ mlir::Value genComplexMathOp(fir::FirOpBuilder &builder, mlir::Location loc, // the argument types for an operation if constexpr (T::template hasTrait< mlir::OpTrait::SameOperandsAndResultType>()) { - result = builder.create(loc, args); + result = T::create(builder, loc, args); result = builder.createConvert(loc, mathLibFuncType.getResult(0), result); } else { auto complexTy = mlir::cast(mathLibFuncType.getInput(0)); auto realTy = complexTy.getElementType(); - result = builder.create(loc, realTy, args); + result = T::create(builder, loc, realTy, args); result = builder.createConvert(loc, mathLibFuncType.getResult(0), result); } @@ -2449,7 +2462,7 @@ IntrinsicLibrary::outlineInWrapper(GeneratorType generator, nameOS << '.' << fmfString; } mlir::func::FuncOp wrapper = getWrapper(generator, funcName, funcType); - return builder.create(loc, wrapper, args).getResult(0); + return fir::CallOp::create(builder, loc, wrapper, args).getResult(0); } template @@ -2465,7 +2478,7 @@ fir::ExtendedValue IntrinsicLibrary::outlineInExtendedWrapper( mlirArgs.emplace_back(toValue(extendedVal, builder, loc)); mlir::FunctionType funcType = getFunctionType(resultType, mlirArgs, builder); mlir::func::FuncOp wrapper = getWrapper(generator, name, funcType); - auto call = builder.create(loc, wrapper, mlirArgs); + auto call = fir::CallOp::create(builder, loc, wrapper, mlirArgs); if (resultType) return toExtendedValue(call.getResult(0), builder, loc); // Subroutine calls @@ -2583,9 +2596,9 @@ IntrinsicLibrary::readAndAddCleanUp(fir::MutableBoxValue resultMutableBox, return box; }, [&](const mlir::Value &tempAddr) -> fir::ExtendedValue { - auto load = builder.create(loc, resultType, tempAddr); + auto load = fir::LoadOp::create(builder, loc, resultType, tempAddr); // Temp can be freed right away since it was loaded. - builder.create(loc, tempAddr); + fir::FreeMemOp::create(builder, loc, tempAddr); return load; }, [&](const fir::CharBoxValue &box) -> fir::ExtendedValue { @@ -2638,9 +2651,9 @@ mlir::Value IntrinsicLibrary::genAbs(mlir::Type resultType, // So, implement abs here without branching. mlir::Value shift = builder.createIntegerConstant(loc, intType, intType.getWidth() - 1); - auto mask = builder.create(loc, arg, shift); - auto xored = builder.create(loc, arg, mask); - return builder.create(loc, xored, mask); + auto mask = mlir::arith::ShRSIOp::create(builder, loc, arg, shift); + auto xored = mlir::arith::XOrIOp::create(builder, loc, arg, mask); + return mlir::arith::SubIOp::create(builder, loc, xored, mask); } llvm_unreachable("unexpected type in ABS argument"); } @@ -2659,7 +2672,7 @@ mlir::Value IntrinsicLibrary::genAcosd(mlir::Type resultType, mlir::Value dfactor = builder.createRealConstant( loc, mlir::Float64Type::get(context), llvm::APFloat(180.0) / pi); mlir::Value factor = builder.createConvert(loc, args[0].getType(), dfactor); - return builder.create(loc, result, factor); + return mlir::arith::MulFOp::create(builder, loc, result, factor); } // ADJUSTL & ADJUSTR @@ -2812,7 +2825,7 @@ mlir::Value IntrinsicLibrary::genAsind(mlir::Type resultType, mlir::Value dfactor = builder.createRealConstant( loc, mlir::Float64Type::get(context), llvm::APFloat(180.0) / pi); mlir::Value factor = builder.createConvert(loc, args[0].getType(), dfactor); - return builder.create(loc, result, factor); + return mlir::arith::MulFOp::create(builder, loc, result, factor); } // ATAND, ATAN2D @@ -2826,8 +2839,8 @@ mlir::Value IntrinsicLibrary::genAtand(mlir::Type resultType, // atand = atan * 180/pi if (args.size() == 2) { - atan = builder.create(loc, fir::getBase(args[0]), - fir::getBase(args[1])); + atan = mlir::math::Atan2Op::create(builder, loc, fir::getBase(args[0]), + fir::getBase(args[1])); } else { mlir::FunctionType ftype = mlir::FunctionType::get(context, {resultType}, {args[0].getType()}); @@ -2837,7 +2850,7 @@ mlir::Value IntrinsicLibrary::genAtand(mlir::Type resultType, mlir::Value dfactor = builder.createRealConstant( loc, mlir::Float64Type::get(context), llvm::APFloat(180.0) / pi); mlir::Value factor = builder.createConvert(loc, resultType, dfactor); - return builder.create(loc, atan, factor); + return mlir::arith::MulFOp::create(builder, loc, atan, factor); } // ATANPI, ATAN2PI @@ -2851,8 +2864,8 @@ mlir::Value IntrinsicLibrary::genAtanpi(mlir::Type resultType, // atanpi = atan / pi if (args.size() == 2) { - atan = builder.create(loc, fir::getBase(args[0]), - fir::getBase(args[1])); + atan = mlir::math::Atan2Op::create(builder, loc, fir::getBase(args[0]), + fir::getBase(args[1])); } else { mlir::FunctionType ftype = mlir::FunctionType::get(context, {resultType}, {args[0].getType()}); @@ -2862,7 +2875,7 @@ mlir::Value IntrinsicLibrary::genAtanpi(mlir::Type resultType, mlir::Value dfactor = builder.createRealConstant(loc, mlir::Float64Type::get(context), inv_pi); mlir::Value factor = builder.createConvert(loc, resultType, dfactor); - return builder.create(loc, atan, factor); + return mlir::arith::MulFOp::create(builder, loc, atan, factor); } static mlir::Value genAtomBinOp(fir::FirOpBuilder &builder, mlir::Location &loc, @@ -2870,8 +2883,8 @@ static mlir::Value genAtomBinOp(fir::FirOpBuilder &builder, mlir::Location &loc, mlir::Value arg1) { auto llvmPointerType = mlir::LLVM::LLVMPointerType::get(builder.getContext()); arg0 = builder.createConvert(loc, llvmPointerType, arg0); - return builder.create( - loc, binOp, arg0, arg1, mlir::LLVM::AtomicOrdering::seq_cst); + return mlir::LLVM::AtomicRMWOp::create(builder, loc, binOp, arg0, arg1, + mlir::LLVM::AtomicOrdering::seq_cst); } mlir::Value IntrinsicLibrary::genAtomicAdd(mlir::Type resultType, @@ -2929,11 +2942,11 @@ IntrinsicLibrary::genAtomicCas(mlir::Type resultType, auto bitCastFloat = [&](mlir::Value arg) -> mlir::Value { if (mlir::isa(arg.getType())) - return builder.create(loc, builder.getI32Type(), - arg); + return mlir::LLVM::BitcastOp::create(builder, loc, builder.getI32Type(), + arg); if (mlir::isa(arg.getType())) - return builder.create(loc, builder.getI64Type(), - arg); + return mlir::LLVM::BitcastOp::create(builder, loc, builder.getI64Type(), + arg); return arg; }; @@ -2946,11 +2959,11 @@ IntrinsicLibrary::genAtomicCas(mlir::Type resultType, } auto address = - builder.create(loc, llvmPtrTy, arg0) + mlir::UnrealizedConversionCastOp::create(builder, loc, llvmPtrTy, arg0) .getResult(0); - auto cmpxchg = builder.create( - loc, address, arg1, arg2, successOrdering, failureOrdering); - return builder.create(loc, cmpxchg, 1); + auto cmpxchg = mlir::LLVM::AtomicCmpXchgOp::create( + builder, loc, address, arg1, arg2, successOrdering, failureOrdering); + return mlir::LLVM::ExtractValueOp::create(builder, loc, cmpxchg, 1); } mlir::Value IntrinsicLibrary::genAtomicDec(mlir::Type resultType, @@ -3026,31 +3039,31 @@ IntrinsicLibrary::genAssociated(mlir::Type resultType, mlir::isa(ptrTy))) { mlir::Value pointerBoxProc = fir::isBoxProcAddressType(ptrTy) - ? builder.create(loc, fir::getBase(args[0])) + ? fir::LoadOp::create(builder, loc, fir::getBase(args[0])) : fir::getBase(args[0]); mlir::Value pointerTarget = - builder.create(loc, pointerBoxProc); + fir::BoxAddrOp::create(builder, loc, pointerBoxProc); if (isStaticallyAbsent(args[1])) return builder.genIsNotNullAddr(loc, pointerTarget); mlir::Value target = fir::getBase(args[1]); if (fir::isBoxProcAddressType(target.getType())) - target = builder.create(loc, target); + target = fir::LoadOp::create(builder, loc, target); if (mlir::isa(target.getType())) - target = builder.create(loc, target); + target = fir::BoxAddrOp::create(builder, loc, target); mlir::Type intPtrTy = builder.getIntPtrType(); mlir::Value pointerInt = builder.createConvert(loc, intPtrTy, pointerTarget); mlir::Value targetInt = builder.createConvert(loc, intPtrTy, target); - mlir::Value sameTarget = builder.create( - loc, mlir::arith::CmpIPredicate::eq, pointerInt, targetInt); + mlir::Value sameTarget = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, pointerInt, targetInt); mlir::Value zero = builder.createIntegerConstant(loc, intPtrTy, 0); - mlir::Value notNull = builder.create( - loc, mlir::arith::CmpIPredicate::ne, zero, pointerInt); + mlir::Value notNull = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::ne, zero, pointerInt); // The not notNull test covers the following two cases: // - TARGET is a procedure that is OPTIONAL and absent at runtime. // - TARGET is a procedure pointer that is NULL. // In both cases, ASSOCIATED should be false if POINTER is NULL. - return builder.create(loc, sameTarget, notNull); + return mlir::arith::AndIOp::create(builder, loc, sameTarget, notNull); } auto *pointer = args[0].match([&](const fir::MutableBoxValue &x) { return &x; }, @@ -3063,7 +3076,7 @@ IntrinsicLibrary::genAssociated(mlir::Type resultType, mlir::Value targetBox = builder.createBox(loc, target); mlir::Value pointerBoxRef = fir::factory::getMutableIRBox(builder, loc, *pointer); - auto pointerBox = builder.create(loc, pointerBoxRef); + auto pointerBox = fir::LoadOp::create(builder, loc, pointerBoxRef); return fir::runtime::genAssociated(builder, loc, pointerBox, targetBox); } @@ -3094,12 +3107,12 @@ IntrinsicLibrary::genBesselJn(mlir::Type resultType, mlir::Value resultBox = fir::factory::getMutableIRBox(builder, loc, resultMutableBox); - mlir::Value cmpXEq0 = builder.create( - loc, mlir::arith::CmpFPredicate::UEQ, x, zero); - mlir::Value cmpN1LtN2 = builder.create( - loc, mlir::arith::CmpIPredicate::slt, n1, n2); - mlir::Value cmpN1EqN2 = builder.create( - loc, mlir::arith::CmpIPredicate::eq, n1, n2); + mlir::Value cmpXEq0 = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::UEQ, x, zero); + mlir::Value cmpN1LtN2 = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::slt, n1, n2); + mlir::Value cmpN1EqN2 = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, n1, n2); auto genXEq0 = [&]() { fir::runtime::genBesselJnX0(builder, loc, floatTy, resultBox, n1, n2); @@ -3111,7 +3124,7 @@ IntrinsicLibrary::genBesselJn(mlir::Type resultType, // https://dlmf.nist.gov/10.6.E1). When n1 < n2, this requires // the values of BESSEL_JN(n2) and BESSEL_JN(n2 - 1) since they // are the anchors of the recursion. - mlir::Value n2_1 = builder.create(loc, n2, one); + mlir::Value n2_1 = mlir::arith::SubIOp::create(builder, loc, n2, one); mlir::Value bn2 = genRuntimeCall("bessel_jn", resultType, {n2, x}); mlir::Value bn2_1 = genRuntimeCall("bessel_jn", resultType, {n2_1, x}); fir::runtime::genBesselJn(builder, loc, resultBox, n1, n2, x, bn2, bn2_1); @@ -3179,12 +3192,12 @@ IntrinsicLibrary::genBesselYn(mlir::Type resultType, mlir::Value resultBox = fir::factory::getMutableIRBox(builder, loc, resultMutableBox); - mlir::Value cmpXEq0 = builder.create( - loc, mlir::arith::CmpFPredicate::UEQ, x, zero); - mlir::Value cmpN1LtN2 = builder.create( - loc, mlir::arith::CmpIPredicate::slt, n1, n2); - mlir::Value cmpN1EqN2 = builder.create( - loc, mlir::arith::CmpIPredicate::eq, n1, n2); + mlir::Value cmpXEq0 = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::UEQ, x, zero); + mlir::Value cmpN1LtN2 = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::slt, n1, n2); + mlir::Value cmpN1EqN2 = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, n1, n2); auto genXEq0 = [&]() { fir::runtime::genBesselYnX0(builder, loc, floatTy, resultBox, n1, n2); @@ -3196,7 +3209,7 @@ IntrinsicLibrary::genBesselYn(mlir::Type resultType, // https://dlmf.nist.gov/10.6.E1). When n1 < n2, this requires // the values of BESSEL_YN(n1) and BESSEL_YN(n1 + 1) since they // are the anchors of the recursion. - mlir::Value n1_1 = builder.create(loc, n1, one); + mlir::Value n1_1 = mlir::arith::AddIOp::create(builder, loc, n1, one); mlir::Value bn1 = genRuntimeCall("bessel_yn", resultType, {n1, x}); mlir::Value bn1_1 = genRuntimeCall("bessel_yn", resultType, {n1_1, x}); fir::runtime::genBesselYn(builder, loc, resultBox, n1, n2, x, bn1, bn1_1); @@ -3268,12 +3281,12 @@ IntrinsicLibrary::genBitwiseCompare(mlir::Type resultType, if (arg0Ty.isUnsignedInteger()) arg0 = builder.createConvert(loc, signlessType, arg0); else if (bits0 < widest) - arg0 = builder.create(loc, signlessType, arg0); + arg0 = mlir::arith::ExtUIOp::create(builder, loc, signlessType, arg0); if (arg1Ty.isUnsignedInteger()) arg1 = builder.createConvert(loc, signlessType, arg1); else if (bits1 < widest) - arg1 = builder.create(loc, signlessType, arg1); - return builder.create(loc, pred, arg0, arg1); + arg1 = mlir::arith::ExtUIOp::create(builder, loc, signlessType, arg1); + return mlir::arith::CmpIOp::create(builder, loc, pred, arg0, arg1); } // BTEST @@ -3292,9 +3305,9 @@ mlir::Value IntrinsicLibrary::genBtest(mlir::Type resultType, word = builder.createConvert(loc, signlessType, word); mlir::Value shiftCount = builder.createConvert(loc, signlessType, args[1]); mlir::Value shifted = - builder.create(loc, word, shiftCount); + mlir::arith::ShRUIOp::create(builder, loc, word, shiftCount); mlir::Value one = builder.createIntegerConstant(loc, signlessType, 1); - mlir::Value bit = builder.create(loc, shifted, one); + mlir::Value bit = mlir::arith::AndIOp::create(builder, loc, shifted, one); return builder.createConvert(loc, resultType, bit); } @@ -3305,11 +3318,11 @@ static mlir::Value getAddrFromBox(fir::FirOpBuilder &builder, mlir::Value addr{nullptr}; if (isFunc) { auto funcTy = mlir::cast(argValue.getType()).getEleTy(); - addr = builder.create(loc, funcTy, argValue); + addr = fir::BoxAddrOp::create(builder, loc, funcTy, argValue); } else { const auto *box = arg.getBoxOf(); - addr = builder.create(loc, box->getMemTy(), - fir::getBase(*box)); + addr = fir::BoxAddrOp::create(builder, loc, box->getMemTy(), + fir::getBase(*box)); } return addr; } @@ -3319,7 +3332,7 @@ genCLocOrCFunLoc(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type resultType, llvm::ArrayRef args, bool isFunc = false, bool isDevLoc = false) { assert(args.size() == 1); - mlir::Value res = builder.create(loc, resultType); + mlir::Value res = fir::AllocaOp::create(builder, loc, resultType); mlir::Value resAddr; if (isDevLoc) resAddr = fir::factory::genCDevPtrAddr(builder, loc, res, resultType); @@ -3330,7 +3343,7 @@ genCLocOrCFunLoc(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value argAddr = getAddrFromBox(builder, loc, args[0], isFunc); mlir::Value argAddrVal = builder.createConvert( loc, fir::unwrapRefType(resAddr.getType()), argAddr); - builder.create(loc, argAddrVal, resAddr); + fir::StoreOp::create(builder, loc, argAddrVal, resAddr); return res; } @@ -3343,8 +3356,8 @@ genCAssociated(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value cPtrVal1 = fir::factory::genCPtrOrCFunptrValue(builder, loc, cPtr1); mlir::Value zero = builder.createIntegerConstant(loc, cPtrVal1.getType(), 0); - mlir::Value res = builder.create( - loc, mlir::arith::CmpIPredicate::ne, cPtrVal1, zero); + mlir::Value res = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::ne, cPtrVal1, zero); if (isStaticallyPresent(args[1])) { mlir::Type i1Ty = builder.getI1Type(); @@ -3353,15 +3366,16 @@ genCAssociated(fir::FirOpBuilder &builder, mlir::Location loc, res = builder .genIfOp(loc, {i1Ty}, isDynamicallyAbsent, /*withElseRegion=*/true) - .genThen([&]() { builder.create(loc, res); }) + .genThen([&]() { fir::ResultOp::create(builder, loc, res); }) .genElse([&]() { mlir::Value cPtrVal2 = fir::factory::genCPtrOrCFunptrValue(builder, loc, cPtr2); - mlir::Value cmpVal = builder.create( - loc, mlir::arith::CmpIPredicate::eq, cPtrVal1, cPtrVal2); + mlir::Value cmpVal = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, cPtrVal1, + cPtrVal2); mlir::Value newRes = - builder.create(loc, res, cmpVal); - builder.create(loc, newRes); + mlir::arith::AndIOp::create(builder, loc, res, cmpVal); + fir::ResultOp::create(builder, loc, newRes); }) .getResults()[0]; } @@ -3416,9 +3430,9 @@ void IntrinsicLibrary::genCFPointer(llvm::ArrayRef args) { mlir::Type idxType = builder.getIndexType(); for (int i = 0; i < arrayRank; ++i) { mlir::Value index = builder.createIntegerConstant(loc, idxType, i); - mlir::Value var = builder.create( - loc, builder.getRefType(shapeElementType), shape, index); - mlir::Value load = builder.create(loc, var); + mlir::Value var = fir::CoordinateOp::create( + builder, loc, builder.getRefType(shapeElementType), shape, index); + mlir::Value load = fir::LoadOp::create(builder, loc, var); extents.push_back(builder.createConvert(loc, idxType, load)); } } @@ -3462,8 +3476,8 @@ void IntrinsicLibrary::genCFProcPointer( mlir::Value cptrCast = builder.createConvert(loc, boxProcType.getEleTy(), cptr); mlir::Value cptrBox = - builder.create(loc, boxProcType, cptrCast); - builder.create(loc, cptrBox, fptr); + fir::EmboxProcOp::create(builder, loc, boxProcType, cptrCast); + fir::StoreOp::create(builder, loc, cptrBox, fptr); } // C_FUNLOC @@ -3493,7 +3507,7 @@ IntrinsicLibrary::genCPtrCompare(mlir::Type resultType, mlir::Value cPtrVal2 = fir::factory::genCPtrOrCFunptrValue(builder, loc, cPtr2); mlir::Value cmp = - builder.create(loc, pred, cPtrVal1, cPtrVal2); + mlir::arith::CmpIOp::create(builder, loc, pred, cPtrVal1, cPtrVal2); return builder.createConvert(loc, resultType, cmp); } @@ -3557,16 +3571,6 @@ IntrinsicLibrary::genChdir(std::optional resultType, return {}; } -// CLOCK64 -mlir::Value IntrinsicLibrary::genClock64(mlir::Type resultType, - llvm::ArrayRef args) { - constexpr llvm::StringLiteral funcName = "llvm.nvvm.read.ptx.sreg.clock64"; - mlir::MLIRContext *context = builder.getContext(); - mlir::FunctionType ftype = mlir::FunctionType::get(context, {}, {resultType}); - auto funcOp = builder.createFunction(loc, funcName, ftype); - return builder.create(loc, funcOp, args).getResult(0); -} - // CMPLX mlir::Value IntrinsicLibrary::genCmplx(mlir::Type resultType, llvm::ArrayRef args) { @@ -3602,7 +3606,7 @@ mlir::Value IntrinsicLibrary::genConjg(mlir::Type resultType, mlir::Value cplx = args[0]; auto imag = fir::factory::Complex{builder, loc}.extractComplexPart( cplx, /*isImagPart=*/true); - auto negImag = builder.create(loc, imag); + auto negImag = mlir::arith::NegFOp::create(builder, loc, imag); return fir::factory::Complex{builder, loc}.insertComplexPart( cplx, negImag, /*isImagPart=*/true); } @@ -3618,7 +3622,22 @@ mlir::Value IntrinsicLibrary::genCosd(mlir::Type resultType, mlir::Value dfactor = builder.createRealConstant( loc, mlir::Float64Type::get(context), pi / llvm::APFloat(180.0)); mlir::Value factor = builder.createConvert(loc, args[0].getType(), dfactor); - mlir::Value arg = builder.create(loc, args[0], factor); + mlir::Value arg = mlir::arith::MulFOp::create(builder, loc, args[0], factor); + return getRuntimeCallGenerator("cos", ftype)(builder, loc, {arg}); +} + +// COSPI +mlir::Value IntrinsicLibrary::genCospi(mlir::Type resultType, + llvm::ArrayRef args) { + assert(args.size() == 1); + mlir::MLIRContext *context = builder.getContext(); + mlir::FunctionType ftype = + mlir::FunctionType::get(context, {resultType}, {args[0].getType()}); + llvm::APFloat pi = llvm::APFloat(llvm::numbers::pi); + mlir::Value dfactor = + builder.createRealConstant(loc, mlir::Float64Type::get(context), pi); + mlir::Value factor = builder.createConvert(loc, args[0].getType(), dfactor); + mlir::Value arg = mlir::arith::MulFOp::create(builder, loc, args[0], factor); return getRuntimeCallGenerator("cos", ftype)(builder, loc, {arg}); } @@ -3679,7 +3698,7 @@ void IntrinsicLibrary::genCpuTime(llvm::ArrayRef args) { mlir::Value res1 = fir::runtime::genCpuTime(builder, loc); mlir::Value res2 = builder.createConvert(loc, fir::dyn_cast_ptrEleTy(arg->getType()), res1); - builder.create(loc, res2, *arg); + fir::StoreOp::create(builder, loc, res2, *arg); } // CSHIFT @@ -3706,7 +3725,7 @@ IntrinsicLibrary::genCshift(mlir::Type resultType, // Handle required SHIFT argument as a scalar const mlir::Value *shiftAddr = args[1].getUnboxed(); assert(shiftAddr && "nonscalar CSHIFT argument"); - auto shift = builder.create(loc, *shiftAddr); + auto shift = fir::LoadOp::create(builder, loc, *shiftAddr); fir::runtime::genCshiftVector(builder, loc, resultIrBox, array, shift); } else { @@ -3732,9 +3751,9 @@ IntrinsicLibrary::genCUDALDXXFunc(mlir::Type resultType, assert(args.size() == 1); mlir::Type resTy = fir::SequenceType::get(extent, resultType); mlir::Value arg = fir::getBase(args[0]); - mlir::Value res = builder.create(loc, resTy); + mlir::Value res = fir::AllocaOp::create(builder, loc, resTy); if (mlir::isa(arg.getType())) - arg = builder.create(loc, arg); + arg = fir::BoxAddrOp::create(builder, loc, arg); mlir::Type refResTy = fir::ReferenceType::get(resTy); mlir::FunctionType ftype = mlir::FunctionType::get(arg.getContext(), {refResTy, refResTy}, {}); @@ -3742,7 +3761,7 @@ IntrinsicLibrary::genCUDALDXXFunc(mlir::Type resultType, llvm::SmallVector funcArgs; funcArgs.push_back(res); funcArgs.push_back(arg); - builder.create(loc, funcOp, funcArgs); + fir::CallOp::create(builder, loc, funcOp, funcArgs); mlir::Value ext = builder.createIntegerConstant(loc, builder.getIndexType(), extent); return fir::ArrayBoxValue(res, {ext}); @@ -3758,8 +3777,8 @@ void IntrinsicLibrary::genDateAndTime(llvm::ArrayRef args) { mlir::Value values = fir::getBase(args[3]); if (!values) - values = builder.create( - loc, fir::BoxType::get(builder.getNoneType())); + values = fir::AbsentOp::create(builder, loc, + fir::BoxType::get(builder.getNoneType())); fir::runtime::genDateAndTime(builder, loc, charArgs[0], charArgs[1], charArgs[2], values); @@ -3771,17 +3790,17 @@ mlir::Value IntrinsicLibrary::genDim(mlir::Type resultType, assert(args.size() == 2); if (mlir::isa(resultType)) { mlir::Value zero = builder.createIntegerConstant(loc, resultType, 0); - auto diff = builder.create(loc, args[0], args[1]); - auto cmp = builder.create( - loc, mlir::arith::CmpIPredicate::sgt, diff, zero); - return builder.create(loc, cmp, diff, zero); + auto diff = mlir::arith::SubIOp::create(builder, loc, args[0], args[1]); + auto cmp = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::sgt, diff, zero); + return mlir::arith::SelectOp::create(builder, loc, cmp, diff, zero); } assert(fir::isa_real(resultType) && "Only expects real and integer in DIM"); mlir::Value zero = builder.createRealZeroConstant(loc, resultType); - auto diff = builder.create(loc, args[0], args[1]); - auto cmp = builder.create( - loc, mlir::arith::CmpFPredicate::OGT, diff, zero); - return builder.create(loc, cmp, diff, zero); + auto diff = mlir::arith::SubFOp::create(builder, loc, args[0], args[1]); + auto cmp = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::OGT, diff, zero); + return mlir::arith::SelectOp::create(builder, loc, cmp, diff, zero); } // DOT_PRODUCT @@ -3799,12 +3818,13 @@ IntrinsicLibrary::genDotProduct(mlir::Type resultType, if (fir::isa_complex(eleTy)) { mlir::Value result = builder.createTemporary(loc, eleTy); fir::runtime::genDotProduct(builder, loc, vectorA, vectorB, result); - return builder.create(loc, result); + return fir::LoadOp::create(builder, loc, result); } // This operation is only used to pass the result type // information to the DotProduct generator. - auto resultBox = builder.create(loc, fir::BoxType::get(eleTy)); + auto resultBox = + fir::AbsentOp::create(builder, loc, fir::BoxType::get(eleTy)); return fir::runtime::genDotProduct(builder, loc, vectorA, vectorB, resultBox); } @@ -3816,7 +3836,7 @@ mlir::Value IntrinsicLibrary::genDprod(mlir::Type resultType, "Result must be double precision in DPROD"); mlir::Value a = builder.createConvert(loc, resultType, args[0]); mlir::Value b = builder.createConvert(loc, resultType, args[1]); - return builder.create(loc, a, b); + return mlir::arith::MulFOp::create(builder, loc, a, b); } // DSHIFTL @@ -3839,14 +3859,14 @@ mlir::Value IntrinsicLibrary::genDshiftl(mlir::Type resultType, // Per the standard, the value of DSHIFTL(I, J, SHIFT) is equal to // IOR (SHIFTL(I, SHIFT), SHIFTR(J, BIT_SIZE(J) - SHIFT)) - mlir::Value diff = builder.create(loc, bitSize, shift); + mlir::Value diff = mlir::arith::SubIOp::create(builder, loc, bitSize, shift); mlir::Value lArgs[2]{i, shift}; mlir::Value lft = genShift(signlessType, lArgs); mlir::Value rArgs[2]{j, diff}; mlir::Value rgt = genShift(signlessType, rArgs); - mlir::Value result = builder.create(loc, lft, rgt); + mlir::Value result = mlir::arith::OrIOp::create(builder, loc, lft, rgt); if (resultType.isUnsignedInteger()) return builder.createConvert(loc, resultType, result); return result; @@ -3872,14 +3892,14 @@ mlir::Value IntrinsicLibrary::genDshiftr(mlir::Type resultType, // Per the standard, the value of DSHIFTR(I, J, SHIFT) is equal to // IOR (SHIFTL(I, BIT_SIZE(I) - SHIFT), SHIFTR(J, SHIFT)) - mlir::Value diff = builder.create(loc, bitSize, shift); + mlir::Value diff = mlir::arith::SubIOp::create(builder, loc, bitSize, shift); mlir::Value lArgs[2]{i, diff}; mlir::Value lft = genShift(signlessType, lArgs); mlir::Value rArgs[2]{j, shift}; mlir::Value rgt = genShift(signlessType, rArgs); - mlir::Value result = builder.create(loc, lft, rgt); + mlir::Value result = mlir::arith::OrIOp::create(builder, loc, lft, rgt); if (resultType.isUnsignedInteger()) return builder.createConvert(loc, resultType, result); return result; @@ -3907,8 +3927,8 @@ IntrinsicLibrary::genEoshift(mlir::Type resultType, // Handle optional BOUNDARY argument mlir::Value boundary = isStaticallyAbsent(args[2]) - ? builder.create( - loc, fir::BoxType::get(builder.getNoneType())) + ? fir::AbsentOp::create(builder, loc, + fir::BoxType::get(builder.getNoneType())) : builder.createBox(loc, args[2]); if (arrayRank == 1) { @@ -3916,7 +3936,7 @@ IntrinsicLibrary::genEoshift(mlir::Type resultType, // Handle required SHIFT argument as a scalar const mlir::Value *shiftAddr = args[1].getUnboxed(); assert(shiftAddr && "nonscalar EOSHIFT SHIFT argument"); - auto shift = builder.create(loc, *shiftAddr); + auto shift = fir::LoadOp::create(builder, loc, *shiftAddr); fir::runtime::genEoshiftVector(builder, loc, resultIrBox, array, shift, boundary); } else { @@ -3964,14 +3984,15 @@ void IntrinsicLibrary::genExecuteCommandLine( .genIfOp(loc, {i1Ty}, waitIsPresentAtRuntime, /*withElseRegion=*/true) .genThen([&]() { - auto waitLoad = builder.create(loc, waitAddr); + auto waitLoad = + fir::LoadOp::create(builder, loc, waitAddr); mlir::Value cast = builder.createConvert(loc, i1Ty, waitLoad); - builder.create(loc, cast); + fir::ResultOp::create(builder, loc, cast); }) .genElse([&]() { mlir::Value trueVal = builder.createBool(loc, true); - builder.create(loc, trueVal); + fir::ResultOp::create(builder, loc, trueVal); }) .getResults()[0]; } @@ -3979,15 +4000,15 @@ void IntrinsicLibrary::genExecuteCommandLine( mlir::Value exitstatBox = isStaticallyPresent(exitstat) ? fir::getBase(exitstat) - : builder.create(loc, boxNoneTy).getResult(); + : fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); mlir::Value cmdstatBox = isStaticallyPresent(cmdstat) ? fir::getBase(cmdstat) - : builder.create(loc, boxNoneTy).getResult(); + : fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); mlir::Value cmdmsgBox = isStaticallyPresent(cmdmsg) ? fir::getBase(cmdmsg) - : builder.create(loc, boxNoneTy).getResult(); + : fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); fir::runtime::genExecuteCommandLine(builder, loc, command, waitBool, exitstatBox, cmdstatBox, cmdmsgBox); } @@ -4008,7 +4029,7 @@ IntrinsicLibrary::genEtime(std::optional resultType, auto timeAddr = builder.createTemporary(loc, *resultType); auto timeBox = builder.createBox(loc, timeAddr); fir::runtime::genEtime(builder, loc, values, timeBox); - return builder.create(loc, timeAddr); + return fir::LoadOp::create(builder, loc, timeAddr); } else { // subroutine form mlir::Value time = fir::getBase(args[1]); @@ -4081,8 +4102,8 @@ IntrinsicLibrary::genFindloc(mlir::Type resultType, // Handle optional mask argument auto mask = isStaticallyAbsent(args[3]) - ? builder.create( - loc, fir::BoxType::get(builder.getI1Type())) + ? fir::AbsentOp::create( + builder, loc, fir::BoxType::get(builder.getI1Type())) : builder.createBox(loc, args[3]); // Handle optional kind argument @@ -4271,15 +4292,15 @@ void IntrinsicLibrary::genGetCommand(llvm::ArrayRef args) { mlir::Value commandBox = isStaticallyPresent(command) ? fir::getBase(command) - : builder.create(loc, boxNoneTy).getResult(); + : fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); mlir::Value lenBox = isStaticallyPresent(length) ? fir::getBase(length) - : builder.create(loc, boxNoneTy).getResult(); + : fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); mlir::Value errBox = isStaticallyPresent(errmsg) ? fir::getBase(errmsg) - : builder.create(loc, boxNoneTy).getResult(); + : fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); mlir::Value stat = fir::runtime::genGetCommand(builder, loc, commandBox, lenBox, errBox); if (isStaticallyPresent(status)) { @@ -4338,15 +4359,15 @@ void IntrinsicLibrary::genGetCommandArgument( mlir::Value valBox = isStaticallyPresent(value) ? fir::getBase(value) - : builder.create(loc, boxNoneTy).getResult(); + : fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); mlir::Value lenBox = isStaticallyPresent(length) ? fir::getBase(length) - : builder.create(loc, boxNoneTy).getResult(); + : fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); mlir::Value errBox = isStaticallyPresent(errmsg) ? fir::getBase(errmsg) - : builder.create(loc, boxNoneTy).getResult(); + : fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); mlir::Value stat = fir::runtime::genGetCommandArgument( builder, loc, number, valBox, lenBox, errBox); if (isStaticallyPresent(status)) { @@ -4391,13 +4412,14 @@ void IntrinsicLibrary::genGetEnvironmentVariable( .genIfOp(loc, {i1Ty}, trimNameIsPresentAtRuntime, /*withElseRegion=*/true) .genThen([&]() { - auto trimLoad = builder.create(loc, trimNameAddr); + auto trimLoad = + fir::LoadOp::create(builder, loc, trimNameAddr); mlir::Value cast = builder.createConvert(loc, i1Ty, trimLoad); - builder.create(loc, cast); + fir::ResultOp::create(builder, loc, cast); }) .genElse([&]() { mlir::Value trueVal = builder.createBool(loc, true); - builder.create(loc, trueVal); + fir::ResultOp::create(builder, loc, trueVal); }) .getResults()[0]; } @@ -4406,15 +4428,15 @@ void IntrinsicLibrary::genGetEnvironmentVariable( mlir::Value valBox = isStaticallyPresent(value) ? fir::getBase(value) - : builder.create(loc, boxNoneTy).getResult(); + : fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); mlir::Value lenBox = isStaticallyPresent(length) ? fir::getBase(length) - : builder.create(loc, boxNoneTy).getResult(); + : fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); mlir::Value errBox = isStaticallyPresent(errmsg) ? fir::getBase(errmsg) - : builder.create(loc, boxNoneTy).getResult(); + : fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); mlir::Value stat = fir::runtime::genGetEnvVariable(builder, loc, name, valBox, lenBox, trim, errBox); if (isStaticallyPresent(status)) { @@ -4499,8 +4521,8 @@ IntrinsicLibrary::genReduction(FN func, FD funcDim, llvm::StringRef errMsg, // Handle optional mask argument auto mask = isStaticallyAbsent(args[2]) - ? builder.create( - loc, fir::BoxType::get(builder.getI1Type())) + ? fir::AbsentOp::create( + builder, loc, fir::BoxType::get(builder.getI1Type())) : builder.createBox(loc, args[2]); bool absentDim = isStaticallyAbsent(args[1]); @@ -4514,10 +4536,10 @@ IntrinsicLibrary::genReduction(FN func, FD funcDim, llvm::StringRef errMsg, if (fir::isa_complex(eleTy)) { mlir::Value result = builder.createTemporary(loc, eleTy); func(builder, loc, array, mask, result); - return builder.create(loc, result); + return fir::LoadOp::create(builder, loc, result); } - auto resultBox = builder.create( - loc, fir::BoxType::get(builder.getI1Type())); + auto resultBox = fir::AbsentOp::create( + builder, loc, fir::BoxType::get(builder.getI1Type())); return func(builder, loc, array, mask, resultBox); } // Handle Product/Sum cases that have an array result. @@ -4564,8 +4586,8 @@ mlir::Value IntrinsicLibrary::genIbclr(mlir::Type resultType, mlir::Value one = builder.createIntegerConstant(loc, signlessType, 1); mlir::Value ones = builder.createAllOnesInteger(loc, signlessType); mlir::Value pos = builder.createConvert(loc, signlessType, args[1]); - mlir::Value bit = builder.create(loc, one, pos); - mlir::Value mask = builder.create(loc, ones, bit); + mlir::Value bit = mlir::arith::ShLIOp::create(builder, loc, one, pos); + mlir::Value mask = mlir::arith::XOrIOp::create(builder, loc, ones, bit); return builder.createUnsigned(loc, resultType, args[0], mask); } @@ -4593,18 +4615,18 @@ mlir::Value IntrinsicLibrary::genIbits(mlir::Type resultType, mlir::Value bitSize = builder.createIntegerConstant( loc, signlessType, mlir::cast(resultType).getWidth()); mlir::Value shiftCount = - builder.create(loc, bitSize, len); + mlir::arith::SubIOp::create(builder, loc, bitSize, len); mlir::Value zero = builder.createIntegerConstant(loc, signlessType, 0); mlir::Value ones = builder.createAllOnesInteger(loc, signlessType); mlir::Value mask = - builder.create(loc, ones, shiftCount); + mlir::arith::ShRUIOp::create(builder, loc, ones, shiftCount); mlir::Value res1 = builder.createUnsigned( loc, signlessType, word, pos); - mlir::Value res2 = builder.create(loc, res1, mask); - mlir::Value lenIsZero = builder.create( - loc, mlir::arith::CmpIPredicate::eq, len, zero); + mlir::Value res2 = mlir::arith::AndIOp::create(builder, loc, res1, mask); + mlir::Value lenIsZero = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, len, zero); mlir::Value result = - builder.create(loc, lenIsZero, zero, res2); + mlir::arith::SelectOp::create(builder, loc, lenIsZero, zero, res2); if (resultType.isUnsignedInteger()) return builder.createConvert(loc, resultType, result); return result; @@ -4623,7 +4645,7 @@ mlir::Value IntrinsicLibrary::genIbset(mlir::Type resultType, mlir::IntegerType::SignednessSemantics::Signless); mlir::Value one = builder.createIntegerConstant(loc, signlessType, 1); mlir::Value pos = builder.createConvert(loc, signlessType, args[1]); - mlir::Value mask = builder.create(loc, one, pos); + mlir::Value mask = mlir::arith::ShLIOp::create(builder, loc, one, pos); return builder.createUnsigned(loc, resultType, args[0], mask); } @@ -4657,13 +4679,13 @@ IntrinsicLibrary::genIchar(mlir::Type resultType, fir::CharacterType::get(builder.getContext(), eleType.getFKind(), 1); mlir::Type toTy = builder.getRefType(charType); mlir::Value cast = builder.createConvert(loc, toTy, buffer); - charVal = builder.create(loc, cast); + charVal = fir::LoadOp::create(builder, loc, cast); } LLVM_DEBUG(llvm::dbgs() << "ichar(" << charVal << ")\n"); auto code = helper.extractCodeFromSingleton(charVal); if (code.getType() == resultType) return code; - return builder.create(loc, resultType, code); + return mlir::arith::ExtUIOp::create(builder, loc, resultType, code); } // llvm floating point class intrinsic test values @@ -4693,7 +4715,7 @@ mlir::Value IntrinsicLibrary::genIsFPClass(mlir::Type resultType, assert(args.size() == 1); mlir::Type i1Ty = builder.getI1Type(); mlir::Value isfpclass = - builder.create(loc, i1Ty, args[0], fpclass); + mlir::LLVM::IsFPClass::create(builder, loc, i1Ty, args[0], fpclass); return builder.createConvert(loc, resultType, isfpclass); } @@ -4708,7 +4730,7 @@ mlir::Value IntrinsicLibrary::genQNan(mlir::Type resultType) { void IntrinsicLibrary::genRaiseExcept(int excepts, mlir::Value cond) { fir::IfOp ifOp; if (cond) { - ifOp = builder.create(loc, cond, /*withElseRegion=*/false); + ifOp = fir::IfOp::create(builder, loc, cond, /*withElseRegion=*/false); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); } mlir::Type i32Ty = builder.getIntegerType(32); @@ -4729,11 +4751,11 @@ getFieldRef(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value rec, mlir::dyn_cast(fir::unwrapPassByRefType(rec.getType())); assert(index < recType.getTypeList().size() && "not enough components"); auto [fieldName, fieldTy] = recType.getTypeList()[index]; - mlir::Value field = builder.create( - loc, fir::FieldType::get(recType.getContext()), fieldName, recType, - fir::getTypeParams(rec)); - return {builder.create(loc, builder.getRefType(fieldTy), - rec, field), + mlir::Value field = fir::FieldIndexOp::create( + builder, loc, fir::FieldType::get(recType.getContext()), fieldName, + recType, fir::getTypeParams(rec)); + return {fir::CoordinateOp::create(builder, loc, builder.getRefType(fieldTy), + rec, field), fieldTy}; } @@ -4746,9 +4768,9 @@ IntrinsicLibrary::genIeeeTypeCompare(mlir::Type resultType, assert(args.size() == 2); auto [leftRef, fieldTy] = getFieldRef(builder, loc, args[0]); auto [rightRef, ignore] = getFieldRef(builder, loc, args[1]); - mlir::Value left = builder.create(loc, fieldTy, leftRef); - mlir::Value right = builder.create(loc, fieldTy, rightRef); - return builder.create(loc, pred, left, right); + mlir::Value left = fir::LoadOp::create(builder, loc, fieldTy, leftRef); + mlir::Value right = fir::LoadOp::create(builder, loc, fieldTy, rightRef); + return mlir::arith::CmpIOp::create(builder, loc, pred, left, right); } // IEEE_CLASS @@ -4779,7 +4801,7 @@ mlir::Value IntrinsicLibrary::genIeeeClass(mlir::Type resultType, const unsigned intWidth = realType.getWidth(); mlir::Type intType = builder.getIntegerType(intWidth); mlir::Value intVal = - builder.create(loc, intType, realVal); + mlir::arith::BitcastOp::create(builder, loc, intType, realVal); llvm::StringRef tableName = RTNAME_STRING(IeeeClassTable); uint64_t highSignificandSize = (realType.getWidth() == 80) + 1; @@ -4789,8 +4811,8 @@ mlir::Value IntrinsicLibrary::genIeeeClass(mlir::Type resultType, return builder.createIntegerConstant(loc, intType, k); }; auto createIntegerConstantAPI = [&](const llvm::APInt &apInt) { - return builder.create( - loc, intType, builder.getIntegerAttr(intType, apInt)); + return mlir::arith::ConstantOp::create( + builder, loc, intType, builder.getIntegerAttr(intType, apInt)); }; auto getMasksAndShifts = [&](uint64_t totalSize, uint64_t exponentSize, uint64_t significandSize, @@ -4837,50 +4859,52 @@ mlir::Value IntrinsicLibrary::genIeeeClass(mlir::Type resultType, // [s] sign bit int pos = 3 + highSignificandSize; - mlir::Value index = builder.create( - loc, builder.create(loc, intVal, signShift), + mlir::Value index = mlir::arith::AndIOp::create( + builder, loc, + mlir::arith::ShRUIOp::create(builder, loc, intVal, signShift), createIntegerConstant(1ULL << pos)); // [e] exponent != 0 mlir::Value exponent = - builder.create(loc, intVal, exponentMask); + mlir::arith::AndIOp::create(builder, loc, intVal, exponentMask); mlir::Value zero = createIntegerConstant(0); - index = builder.create( - loc, index, - builder.create( - loc, - builder.create( - loc, mlir::arith::CmpIPredicate::ne, exponent, zero), + index = mlir::arith::OrIOp::create( + builder, loc, index, + mlir::arith::SelectOp::create( + builder, loc, + mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::ne, exponent, zero), createIntegerConstant(1ULL << --pos), zero)); // [m] exponent == 1..1 (max exponent) - index = builder.create( - loc, index, - builder.create( - loc, - builder.create( - loc, mlir::arith::CmpIPredicate::eq, exponent, exponentMask), + index = mlir::arith::OrIOp::create( + builder, loc, index, + mlir::arith::SelectOp::create( + builder, loc, + mlir::arith::CmpIOp::create(builder, loc, + mlir::arith::CmpIPredicate::eq, exponent, + exponentMask), createIntegerConstant(1ULL << --pos), zero)); // [l] low-order significand != 0 - index = builder.create( - loc, index, - builder.create( - loc, - builder.create( - loc, mlir::arith::CmpIPredicate::ne, - builder.create(loc, intVal, - lowSignificandMask), + index = mlir::arith::OrIOp::create( + builder, loc, index, + mlir::arith::SelectOp::create( + builder, loc, + mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::ne, + mlir::arith::AndIOp::create(builder, loc, intVal, + lowSignificandMask), zero), createIntegerConstant(1ULL << --pos), zero)); // [h] high-order significand (1 or 2 bits) - index = builder.create( - loc, index, - builder.create( - loc, - builder.create(loc, intVal, - highSignificandShift), + index = mlir::arith::OrIOp::create( + builder, loc, index, + mlir::arith::AndIOp::create( + builder, loc, + mlir::arith::ShRUIOp::create(builder, loc, intVal, + highSignificandShift), createIntegerConstant((1 << highSignificandSize) - 1))); int tableSize = 1 << (4 + highSignificandSize); @@ -5008,10 +5032,10 @@ mlir::Value IntrinsicLibrary::genIeeeClass(mlir::Type resultType, mlir::RankedTensorType::get(tableSize, int8Ty), values)); } - return builder.create( - loc, builder.getRefType(resultType), - builder.create(loc, builder.getRefType(tableTy), - builder.getSymbolRefAttr(tableName)), + return fir::CoordinateOp::create( + builder, loc, builder.getRefType(resultType), + fir::AddrOfOp::create(builder, loc, builder.getRefType(tableTy), + builder.getSymbolRefAttr(tableName)), index); } @@ -5038,34 +5062,36 @@ IntrinsicLibrary::genIeeeCopySign(mlir::Type resultType, // Args have the same type. if (xRealType == yRealType) - return builder.create(loc, xRealVal, yRealVal); + return mlir::math::CopySignOp::create(builder, loc, xRealVal, yRealVal); // Args have different types. mlir::Type xIntType = builder.getIntegerType(xRealType.getWidth()); mlir::Type yIntType = builder.getIntegerType(yRealType.getWidth()); mlir::Value xIntVal = - builder.create(loc, xIntType, xRealVal); + mlir::arith::BitcastOp::create(builder, loc, xIntType, xRealVal); mlir::Value yIntVal = - builder.create(loc, yIntType, yRealVal); + mlir::arith::BitcastOp::create(builder, loc, yIntType, yRealVal); mlir::Value xZero = builder.createIntegerConstant(loc, xIntType, 0); mlir::Value yZero = builder.createIntegerConstant(loc, yIntType, 0); mlir::Value xOne = builder.createIntegerConstant(loc, xIntType, 1); - mlir::Value ySign = builder.create( - loc, yIntVal, + mlir::Value ySign = mlir::arith::ShRUIOp::create( + builder, loc, yIntVal, builder.createIntegerConstant(loc, yIntType, yRealType.getWidth() - 1)); - mlir::Value xAbs = builder.create( - loc, builder.create(loc, xIntVal, xOne), xOne); - mlir::Value xSign = builder.create( - loc, - builder.create(loc, mlir::arith::CmpIPredicate::eq, - ySign, yZero), + mlir::Value xAbs = mlir::arith::ShRUIOp::create( + builder, loc, mlir::arith::ShLIOp::create(builder, loc, xIntVal, xOne), + xOne); + mlir::Value xSign = mlir::arith::SelectOp::create( + builder, loc, + mlir::arith::CmpIOp::create(builder, loc, mlir::arith::CmpIPredicate::eq, + ySign, yZero), xZero, - builder.create( - loc, xOne, + mlir::arith::ShLIOp::create( + builder, loc, xOne, builder.createIntegerConstant(loc, xIntType, xRealType.getWidth() - 1))); - return builder.create( - loc, xRealType, builder.create(loc, xAbs, xSign)); + return mlir::arith::BitcastOp::create( + builder, loc, xRealType, + mlir::arith::OrIOp::create(builder, loc, xAbs, xSign)); } // IEEE_GET_FLAG @@ -5079,16 +5105,16 @@ void IntrinsicLibrary::genIeeeGetFlag(llvm::ArrayRef args) { mlir::Type i32Ty = builder.getIntegerType(32); mlir::Value zero = builder.createIntegerConstant(loc, i32Ty, 0); auto [fieldRef, ignore] = getFieldRef(builder, loc, flag); - mlir::Value field = builder.create(loc, fieldRef); + mlir::Value field = fir::LoadOp::create(builder, loc, fieldRef); mlir::Value excepts = fir::runtime::genFetestexcept( builder, loc, fir::runtime::genMapExcept( - builder, loc, builder.create(loc, i32Ty, field))); - mlir::Value logicalResult = builder.create( - loc, resultTy, - builder.create(loc, mlir::arith::CmpIPredicate::ne, - excepts, zero)); - builder.create(loc, logicalResult, flagValue); + builder, loc, fir::ConvertOp::create(builder, loc, i32Ty, field))); + mlir::Value logicalResult = fir::ConvertOp::create( + builder, loc, resultTy, + mlir::arith::CmpIOp::create(builder, loc, mlir::arith::CmpIPredicate::ne, + excepts, zero)); + fir::StoreOp::create(builder, loc, logicalResult, flagValue); } // IEEE_GET_HALTING_MODE @@ -5103,17 +5129,17 @@ void IntrinsicLibrary::genIeeeGetHaltingMode( mlir::Type i32Ty = builder.getIntegerType(32); mlir::Value zero = builder.createIntegerConstant(loc, i32Ty, 0); auto [fieldRef, ignore] = getFieldRef(builder, loc, flag); - mlir::Value field = builder.create(loc, fieldRef); + mlir::Value field = fir::LoadOp::create(builder, loc, fieldRef); mlir::Value haltSet = fir::runtime::genFegetexcept(builder, loc); - mlir::Value intResult = builder.create( - loc, haltSet, + mlir::Value intResult = mlir::arith::AndIOp::create( + builder, loc, haltSet, fir::runtime::genMapExcept( - builder, loc, builder.create(loc, i32Ty, field))); - mlir::Value logicalResult = builder.create( - loc, resultTy, - builder.create(loc, mlir::arith::CmpIPredicate::ne, - intResult, zero)); - builder.create(loc, logicalResult, halting); + builder, loc, fir::ConvertOp::create(builder, loc, i32Ty, field))); + mlir::Value logicalResult = fir::ConvertOp::create( + builder, loc, resultTy, + mlir::arith::CmpIOp::create(builder, loc, mlir::arith::CmpIPredicate::ne, + intResult, zero)); + fir::StoreOp::create(builder, loc, logicalResult, halting); } // IEEE_GET_MODES, IEEE_SET_MODES @@ -5138,34 +5164,34 @@ void IntrinsicLibrary::genIeeeGetOrSetModesOrStatus( // allotment. Allocate data space from the heap. auto [fieldRef, fieldTy] = getFieldRef(builder, loc, fir::getBase(args[0]), 1); - addr = builder.create( - loc, builder.create(loc, fieldRef)); + addr = fir::BoxAddrOp::create(builder, loc, + fir::LoadOp::create(builder, loc, fieldRef)); mlir::Type heapTy = addr.getType(); - mlir::Value allocated = builder.create( - loc, mlir::arith::CmpIPredicate::ne, + mlir::Value allocated = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::ne, builder.createConvert(loc, i64Ty, addr), builder.createIntegerConstant(loc, i64Ty, 0)); - auto ifOp = builder.create(loc, heapTy, allocated, - /*withElseRegion=*/true); + auto ifOp = fir::IfOp::create(builder, loc, heapTy, allocated, + /*withElseRegion=*/true); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); - builder.create(loc, addr); + fir::ResultOp::create(builder, loc, addr); builder.setInsertionPointToStart(&ifOp.getElseRegion().front()); mlir::Value byteSize = isModes ? fir::runtime::genGetModesTypeSize(builder, loc) : fir::runtime::genGetStatusTypeSize(builder, loc); byteSize = builder.createConvert(loc, builder.getIndexType(), byteSize); - addr = builder.create(loc, extractSequenceType(heapTy), - /*typeparams=*/mlir::ValueRange(), - byteSize); - mlir::Value shape = builder.create(loc, byteSize); - builder.create( - loc, builder.create(loc, fieldTy, addr, shape), fieldRef); - builder.create(loc, addr); + addr = fir::AllocMemOp::create(builder, loc, extractSequenceType(heapTy), + /*typeparams=*/mlir::ValueRange(), byteSize); + mlir::Value shape = fir::ShapeOp::create(builder, loc, byteSize); + fir::StoreOp::create( + builder, loc, fir::EmboxOp::create(builder, loc, fieldTy, addr, shape), + fieldRef); + fir::ResultOp::create(builder, loc, addr); builder.setInsertionPointAfter(ifOp); - addr = builder.create(loc, ptrTy, ifOp.getResult(0)); + addr = fir::ConvertOp::create(builder, loc, ptrTy, ifOp.getResult(0)); } else { // Place floating point environment data in __data storage. - addr = builder.create(loc, ptrTy, getBase(args[0])); + addr = fir::ConvertOp::create(builder, loc, ptrTy, getBase(args[0])); } llvm::StringRef func = isModes ? (isGet ? "fegetmode" : "fesetmode") : (isGet ? "fegetenv" : "fesetenv"); @@ -5176,11 +5202,11 @@ void IntrinsicLibrary::genIeeeGetOrSetModesOrStatus( // Check that an explicit ieee_[get|set]_rounding_mode call radix value is 2. static void checkRadix(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value radix, std::string procName) { - mlir::Value notTwo = builder.create( - loc, mlir::arith::CmpIPredicate::ne, radix, + mlir::Value notTwo = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::ne, radix, builder.createIntegerConstant(loc, radix.getType(), 2)); - auto ifOp = builder.create(loc, notTwo, - /*withElseRegion=*/false); + auto ifOp = fir::IfOp::create(builder, loc, notTwo, + /*withElseRegion=*/false); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); fir::runtime::genReportFatalUserError(builder, loc, procName + " radix argument must be 2"); @@ -5198,9 +5224,9 @@ void IntrinsicLibrary::genIeeeGetRoundingMode( checkRadix(builder, loc, fir::getBase(args[1]), "ieee_get_rounding_mode"); auto [fieldRef, fieldTy] = getFieldRef(builder, loc, fir::getBase(args[0])); mlir::func::FuncOp getRound = fir::factory::getLlvmGetRounding(builder); - mlir::Value mode = builder.create(loc, getRound).getResult(0); + mlir::Value mode = fir::CallOp::create(builder, loc, getRound).getResult(0); mode = builder.createConvert(loc, fieldTy, mode); - builder.create(loc, mode, fieldRef); + fir::StoreOp::create(builder, loc, mode, fieldRef); } // IEEE_GET_UNDERFLOW_MODE @@ -5225,44 +5251,45 @@ mlir::Value IntrinsicLibrary::genIeeeInt(mlir::Type resultType, mlir::FloatType realType = mlir::cast(args[0].getType()); mlir::Value realResult = genIeeeRint(realType, {args[0], args[1]}); int intWidth = mlir::cast(resultType).getWidth(); - mlir::Value intLBound = builder.create( - loc, resultType, + mlir::Value intLBound = mlir::arith::ConstantOp::create( + builder, loc, resultType, builder.getIntegerAttr(resultType, llvm::APInt::getBitsSet(intWidth, /*lo=*/intWidth - 1, /*hi=*/intWidth))); - mlir::Value intUBound = builder.create( - loc, resultType, + mlir::Value intUBound = mlir::arith::ConstantOp::create( + builder, loc, resultType, builder.getIntegerAttr(resultType, llvm::APInt::getBitsSet(intWidth, /*lo=*/0, /*hi=*/intWidth - 1))); mlir::Value realLBound = - builder.create(loc, realType, intLBound); - mlir::Value realUBound = builder.create(loc, realLBound); - mlir::Value aGreaterThanLBound = builder.create( - loc, mlir::arith::CmpFPredicate::OGE, realResult, realLBound); - mlir::Value aLessThanUBound = builder.create( - loc, mlir::arith::CmpFPredicate::OLT, realResult, realUBound); - mlir::Value resultIsValid = builder.create( - loc, aGreaterThanLBound, aLessThanUBound); + fir::ConvertOp::create(builder, loc, realType, intLBound); + mlir::Value realUBound = + mlir::arith::NegFOp::create(builder, loc, realLBound); + mlir::Value aGreaterThanLBound = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::OGE, realResult, realLBound); + mlir::Value aLessThanUBound = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::OLT, realResult, realUBound); + mlir::Value resultIsValid = mlir::arith::AndIOp::create( + builder, loc, aGreaterThanLBound, aLessThanUBound); // Result is valid. It may be exact or inexact. mlir::Value result; - fir::IfOp ifOp = builder.create(loc, resultType, resultIsValid, - /*withElseRegion=*/true); + fir::IfOp ifOp = fir::IfOp::create(builder, loc, resultType, resultIsValid, + /*withElseRegion=*/true); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); - mlir::Value inexact = builder.create( - loc, mlir::arith::CmpFPredicate::ONE, args[0], realResult); + mlir::Value inexact = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::ONE, args[0], realResult); genRaiseExcept(_FORTRAN_RUNTIME_IEEE_INEXACT, inexact); - result = builder.create(loc, resultType, realResult); - builder.create(loc, result); + result = fir::ConvertOp::create(builder, loc, resultType, realResult); + fir::ResultOp::create(builder, loc, result); // Result is invalid. builder.setInsertionPointToStart(&ifOp.getElseRegion().front()); genRaiseExcept(_FORTRAN_RUNTIME_IEEE_INVALID); - result = builder.create(loc, aGreaterThanLBound, - intUBound, intLBound); - builder.create(loc, result); + result = mlir::arith::SelectOp::create(builder, loc, aGreaterThanLBound, + intUBound, intLBound); + fir::ResultOp::create(builder, loc, result); builder.setInsertionPointAfter(ifOp); return ifOp.getResult(0); } @@ -5317,7 +5344,7 @@ mlir::Value IntrinsicLibrary::genIeeeLogb(mlir::Type resultType, int bitWidth = realType.getWidth(); mlir::Type intType = builder.getIntegerType(realType.getWidth()); mlir::Value intVal = - builder.create(loc, intType, realVal); + mlir::arith::BitcastOp::create(builder, loc, intType, realVal); mlir::Type i1Ty = builder.getI1Type(); int exponentBias, significandSize, nonSignificandSize; @@ -5364,72 +5391,72 @@ mlir::Value IntrinsicLibrary::genIeeeLogb(mlir::Type resultType, llvm_unreachable("unknown real type"); } - mlir::Value isZero = builder.create( - loc, mlir::arith::CmpFPredicate::OEQ, realVal, + mlir::Value isZero = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::OEQ, realVal, builder.createRealZeroConstant(loc, resultType)); - auto outerIfOp = builder.create(loc, resultType, isZero, - /*withElseRegion=*/true); + auto outerIfOp = fir::IfOp::create(builder, loc, resultType, isZero, + /*withElseRegion=*/true); // X is zero -- result is -infinity builder.setInsertionPointToStart(&outerIfOp.getThenRegion().front()); genRaiseExcept(_FORTRAN_RUNTIME_IEEE_DIVIDE_BY_ZERO); mlir::Value ones = builder.createAllOnesInteger(loc, intType); - mlir::Value result = builder.create( - loc, ones, + mlir::Value result = mlir::arith::ShLIOp::create( + builder, loc, ones, builder.createIntegerConstant(loc, intType, // kind=10 high-order bit is explicit significandSize - (bitWidth == 80))); - result = builder.create(loc, resultType, result); - builder.create(loc, result); + result = mlir::arith::BitcastOp::create(builder, loc, resultType, result); + fir::ResultOp::create(builder, loc, result); builder.setInsertionPointToStart(&outerIfOp.getElseRegion().front()); mlir::Value one = builder.createIntegerConstant(loc, intType, 1); mlir::Value shiftLeftOne = - builder.create(loc, intVal, one); + mlir::arith::ShLIOp::create(builder, loc, intVal, one); mlir::Value isFinite = genIsFPClass(i1Ty, args, finiteTest); - auto innerIfOp = builder.create(loc, resultType, isFinite, - /*withElseRegion=*/true); + auto innerIfOp = fir::IfOp::create(builder, loc, resultType, isFinite, + /*withElseRegion=*/true); // X is non-zero finite -- result is unbiased exponent of X builder.setInsertionPointToStart(&innerIfOp.getThenRegion().front()); mlir::Value isNormal = genIsFPClass(i1Ty, args, normalTest); - auto normalIfOp = builder.create(loc, resultType, isNormal, - /*withElseRegion=*/true); + auto normalIfOp = fir::IfOp::create(builder, loc, resultType, isNormal, + /*withElseRegion=*/true); // X is normal builder.setInsertionPointToStart(&normalIfOp.getThenRegion().front()); - mlir::Value biasedExponent = builder.create( - loc, shiftLeftOne, + mlir::Value biasedExponent = mlir::arith::ShRUIOp::create( + builder, loc, shiftLeftOne, builder.createIntegerConstant(loc, intType, significandSize + 1)); - result = builder.create( - loc, biasedExponent, + result = mlir::arith::SubIOp::create( + builder, loc, biasedExponent, builder.createIntegerConstant(loc, intType, exponentBias)); - result = builder.create(loc, resultType, result); - builder.create(loc, result); + result = fir::ConvertOp::create(builder, loc, resultType, result); + fir::ResultOp::create(builder, loc, result); // X is denormal -- result is (-exponentBias - ctlz(significand)) builder.setInsertionPointToStart(&normalIfOp.getElseRegion().front()); - mlir::Value significand = builder.create( - loc, intVal, + mlir::Value significand = mlir::arith::ShLIOp::create( + builder, loc, intVal, builder.createIntegerConstant(loc, intType, nonSignificandSize)); mlir::Value ctlz = - builder.create(loc, significand); + mlir::math::CountLeadingZerosOp::create(builder, loc, significand); mlir::Type i32Ty = builder.getI32Type(); - result = builder.create( - loc, builder.createIntegerConstant(loc, i32Ty, -exponentBias), - builder.create(loc, i32Ty, ctlz)); - result = builder.create(loc, resultType, result); - builder.create(loc, result); + result = mlir::arith::SubIOp::create( + builder, loc, builder.createIntegerConstant(loc, i32Ty, -exponentBias), + fir::ConvertOp::create(builder, loc, i32Ty, ctlz)); + result = fir::ConvertOp::create(builder, loc, resultType, result); + fir::ResultOp::create(builder, loc, result); builder.setInsertionPointToEnd(&innerIfOp.getThenRegion().front()); - builder.create(loc, normalIfOp.getResult(0)); + fir::ResultOp::create(builder, loc, normalIfOp.getResult(0)); // X is infinity or NaN -- result is +infinity or NaN builder.setInsertionPointToStart(&innerIfOp.getElseRegion().front()); - result = builder.create(loc, shiftLeftOne, one); - result = builder.create(loc, resultType, result); - builder.create(loc, result); + result = mlir::arith::ShRUIOp::create(builder, loc, shiftLeftOne, one); + result = mlir::arith::BitcastOp::create(builder, loc, resultType, result); + fir::ResultOp::create(builder, loc, result); // Unwind the if nest. builder.setInsertionPointToEnd(&outerIfOp.getElseRegion().front()); - builder.create(loc, innerIfOp.getResult(0)); + fir::ResultOp::create(builder, loc, innerIfOp.getResult(0)); builder.setInsertionPointAfter(outerIfOp); return outerIfOp.getResult(0); } @@ -5463,8 +5490,8 @@ mlir::Value IntrinsicLibrary::genIeeeMaxMin(mlir::Type resultType, mlir::Value x1, y1; // X or ABS(X), Y or ABS(Y) if constexpr (isMag) { mlir::Value zero = builder.createRealZeroConstant(loc, resultType); - x1 = builder.create(loc, x, zero); - y1 = builder.create(loc, y, zero); + x1 = mlir::math::CopySignOp::create(builder, loc, x, zero); + y1 = mlir::math::CopySignOp::create(builder, loc, y, zero); } else { x1 = x; y1 = y; @@ -5475,56 +5502,56 @@ mlir::Value IntrinsicLibrary::genIeeeMaxMin(mlir::Type resultType, // X1 < Y1 -- MAX result is Y; MIN result is X. pred = mlir::arith::CmpFPredicate::OLT; - cmp = builder.create(loc, pred, x1, y1); - auto ifOp1 = builder.create(loc, resultType, cmp, true); + cmp = mlir::arith::CmpFOp::create(builder, loc, pred, x1, y1); + auto ifOp1 = fir::IfOp::create(builder, loc, resultType, cmp, true); builder.setInsertionPointToStart(&ifOp1.getThenRegion().front()); result = isMax ? y : x; - builder.create(loc, result); + fir::ResultOp::create(builder, loc, result); // X1 > Y1 -- MAX result is X; MIN result is Y. builder.setInsertionPointToStart(&ifOp1.getElseRegion().front()); pred = mlir::arith::CmpFPredicate::OGT; - cmp = builder.create(loc, pred, x1, y1); - auto ifOp2 = builder.create(loc, resultType, cmp, true); + cmp = mlir::arith::CmpFOp::create(builder, loc, pred, x1, y1); + auto ifOp2 = fir::IfOp::create(builder, loc, resultType, cmp, true); builder.setInsertionPointToStart(&ifOp2.getThenRegion().front()); result = isMax ? x : y; - builder.create(loc, result); + fir::ResultOp::create(builder, loc, result); // X1 == Y1 -- MAX favors a positive result; MIN favors a negative result. builder.setInsertionPointToStart(&ifOp2.getElseRegion().front()); pred = mlir::arith::CmpFPredicate::OEQ; - cmp = builder.create(loc, pred, x1, y1); - auto ifOp3 = builder.create(loc, resultType, cmp, true); + cmp = mlir::arith::CmpFOp::create(builder, loc, pred, x1, y1); + auto ifOp3 = fir::IfOp::create(builder, loc, resultType, cmp, true); builder.setInsertionPointToStart(&ifOp3.getThenRegion().front()); resultIsX = isMax ? genIsFPClass(i1Ty, x, positiveTest) : genIsFPClass(i1Ty, x, negativeTest); - result = builder.create(loc, resultIsX, x, y); - builder.create(loc, result); + result = mlir::arith::SelectOp::create(builder, loc, resultIsX, x, y); + fir::ResultOp::create(builder, loc, result); // X or Y or both are NaNs -- result may be X, Y, or a qNaN builder.setInsertionPointToStart(&ifOp3.getElseRegion().front()); if constexpr (isNum) { pred = mlir::arith::CmpFPredicate::ORD; // check for a non-NaN - resultIsX = builder.create(loc, pred, x, x); - resultIsY = builder.create(loc, pred, y, y); + resultIsX = mlir::arith::CmpFOp::create(builder, loc, pred, x, x); + resultIsY = mlir::arith::CmpFOp::create(builder, loc, pred, y, y); } else { resultIsX = resultIsY = builder.createBool(loc, false); } - result = builder.create( - loc, resultIsX, x, - builder.create(loc, resultIsY, y, - genQNan(resultType))); - mlir::Value hasSNaNOp = builder.create( - loc, genIsFPClass(builder.getI1Type(), args[0], snanTest), + result = mlir::arith::SelectOp::create( + builder, loc, resultIsX, x, + mlir::arith::SelectOp::create(builder, loc, resultIsY, y, + genQNan(resultType))); + mlir::Value hasSNaNOp = mlir::arith::OrIOp::create( + builder, loc, genIsFPClass(builder.getI1Type(), args[0], snanTest), genIsFPClass(builder.getI1Type(), args[1], snanTest)); genRaiseExcept(_FORTRAN_RUNTIME_IEEE_INVALID, hasSNaNOp); - builder.create(loc, result); + fir::ResultOp::create(builder, loc, result); // Unwind the if nest. builder.setInsertionPointAfter(ifOp3); - builder.create(loc, ifOp3.getResult(0)); + fir::ResultOp::create(builder, loc, ifOp3.getResult(0)); builder.setInsertionPointAfter(ifOp2); - builder.create(loc, ifOp2.getResult(0)); + fir::ResultOp::create(builder, loc, ifOp2.getResult(0)); builder.setInsertionPointAfter(ifOp1); return ifOp1.getResult(0); } @@ -5537,13 +5564,13 @@ IntrinsicLibrary::genIeeeQuietCompare(mlir::Type resultType, llvm::ArrayRef args) { // Compare X and Y with special case treatment of NaN operands. assert(args.size() == 2); - mlir::Value hasSNaNOp = builder.create( - loc, genIsFPClass(builder.getI1Type(), args[0], snanTest), + mlir::Value hasSNaNOp = mlir::arith::OrIOp::create( + builder, loc, genIsFPClass(builder.getI1Type(), args[0], snanTest), genIsFPClass(builder.getI1Type(), args[1], snanTest)); mlir::Value res = - builder.create(loc, pred, args[0], args[1]); + mlir::arith::CmpFOp::create(builder, loc, pred, args[0], args[1]); genRaiseExcept(_FORTRAN_RUNTIME_IEEE_INVALID, hasSNaNOp); - return builder.create(loc, resultType, res); + return fir::ConvertOp::create(builder, loc, resultType, res); } // IEEE_REAL @@ -5595,14 +5622,14 @@ mlir::Value IntrinsicLibrary::genIeeeReal(mlir::Type resultType, // If the argument is an sNaN, raise an invalid exception and return a qNaN. // Otherwise return the argument. auto processSnan = [&](mlir::Value x) { - fir::IfOp ifOp = builder.create(loc, resultType, - genIsFPClass(i1Ty, x, snanTest), - /*withElseRegion=*/true); + fir::IfOp ifOp = fir::IfOp::create(builder, loc, resultType, + genIsFPClass(i1Ty, x, snanTest), + /*withElseRegion=*/true); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); genRaiseExcept(_FORTRAN_RUNTIME_IEEE_INVALID); - builder.create(loc, genQNan(resultType)); + fir::ResultOp::create(builder, loc, genQNan(resultType)); builder.setInsertionPointToStart(&ifOp.getElseRegion().front()); - builder.create(loc, x); + fir::ResultOp::create(builder, loc, x); builder.setInsertionPointAfter(ifOp); return ifOp.getResult(0); }; @@ -5618,7 +5645,7 @@ mlir::Value IntrinsicLibrary::genIeeeReal(mlir::Type resultType, a = builder.createConvert(loc, f32Ty, a); aType = f32Ty; } - r = builder.create(loc, resultType, a); + r = fir::ConvertOp::create(builder, loc, resultType, a); mlir::IntegerType aIntType = mlir::dyn_cast(aType); mlir::FloatType aFloatType = mlir::dyn_cast(aType); @@ -5630,142 +5657,144 @@ mlir::Value IntrinsicLibrary::genIeeeReal(mlir::Type resultType, return aIntType ? r : processSnan(r); // A possibly inexact conversion result may need to be rounded up or down. - mlir::Value b = builder.create(loc, aType, r); + mlir::Value b = fir::ConvertOp::create(builder, loc, aType, r); mlir::Value aEqB; if (aIntType) - aEqB = builder.create( - loc, mlir::arith::CmpIPredicate::eq, a, b); + aEqB = mlir::arith::CmpIOp::create(builder, loc, + mlir::arith::CmpIPredicate::eq, a, b); else - aEqB = builder.create( - loc, mlir::arith::CmpFPredicate::UEQ, a, b); + aEqB = mlir::arith::CmpFOp::create(builder, loc, + mlir::arith::CmpFPredicate::UEQ, a, b); // [a == b] a is a NaN or r is exact (a may be -0, +0, -inf, +inf) -- return r - fir::IfOp ifOp1 = builder.create(loc, resultType, aEqB, - /*withElseRegion=*/true); + fir::IfOp ifOp1 = fir::IfOp::create(builder, loc, resultType, aEqB, + /*withElseRegion=*/true); builder.setInsertionPointToStart(&ifOp1.getThenRegion().front()); - builder.create(loc, aIntType ? r : processSnan(r)); + fir::ResultOp::create(builder, loc, aIntType ? r : processSnan(r)); // Code common to (a < b) and (a > b) branches. builder.setInsertionPointToStart(&ifOp1.getElseRegion().front()); mlir::func::FuncOp getRound = fir::factory::getLlvmGetRounding(builder); - mlir::Value mode = builder.create(loc, getRound).getResult(0); + mlir::Value mode = fir::CallOp::create(builder, loc, getRound).getResult(0); mlir::Value aIsNegative, aIsPositive; if (aIntType) { mlir::Value zero = builder.createIntegerConstant(loc, aIntType, 0); - aIsNegative = builder.create( - loc, mlir::arith::CmpIPredicate::slt, a, zero); - aIsPositive = builder.create( - loc, mlir::arith::CmpIPredicate::sgt, a, zero); + aIsNegative = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::slt, a, zero); + aIsPositive = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::sgt, a, zero); } else { mlir::Value zero = builder.createRealZeroConstant(loc, aFloatType); - aIsNegative = builder.create( - loc, mlir::arith::CmpFPredicate::OLT, a, zero); - aIsPositive = builder.create( - loc, mlir::arith::CmpFPredicate::OGT, a, zero); + aIsNegative = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::OLT, a, zero); + aIsPositive = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::OGT, a, zero); } mlir::Type resultIntType = builder.getIntegerType(resultFloatType.getWidth()); mlir::Value resultCast = - builder.create(loc, resultIntType, r); + mlir::arith::BitcastOp::create(builder, loc, resultIntType, r); mlir::Value one = builder.createIntegerConstant(loc, resultIntType, 1); - mlir::Value rIsOdd = builder.create( - loc, i1Ty, builder.create(loc, resultCast, one)); + mlir::Value rIsOdd = fir::ConvertOp::create( + builder, loc, i1Ty, + mlir::arith::AndIOp::create(builder, loc, resultCast, one)); // Check for a rounding mode match. auto match = [&](int m) { - return builder.create( - loc, mlir::arith::CmpIPredicate::eq, mode, + return mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, mode, builder.createIntegerConstant(loc, mode.getType(), m)); }; - mlir::Value roundToNearestBit = builder.create( - loc, + mlir::Value roundToNearestBit = mlir::arith::OrIOp::create( + builder, loc, // IEEE_OTHER is an alias for IEEE_NEAREST. match(_FORTRAN_RUNTIME_IEEE_NEAREST), match(_FORTRAN_RUNTIME_IEEE_OTHER)); mlir::Value roundToNearest = - builder.create(loc, roundToNearestBit, rIsOdd); + mlir::arith::AndIOp::create(builder, loc, roundToNearestBit, rIsOdd); mlir::Value roundToZeroBit = match(_FORTRAN_RUNTIME_IEEE_TO_ZERO); mlir::Value roundAwayBit = match(_FORTRAN_RUNTIME_IEEE_AWAY); mlir::Value roundToZero, roundAway, mustAdjust; fir::IfOp adjustIfOp; mlir::Value aLtB; if (aIntType) - aLtB = builder.create( - loc, mlir::arith::CmpIPredicate::slt, a, b); + aLtB = mlir::arith::CmpIOp::create(builder, loc, + mlir::arith::CmpIPredicate::slt, a, b); else - aLtB = builder.create( - loc, mlir::arith::CmpFPredicate::OLT, a, b); + aLtB = mlir::arith::CmpFOp::create(builder, loc, + mlir::arith::CmpFPredicate::OLT, a, b); mlir::Value upResult = - builder.create(loc, resultCast, one); + mlir::arith::AddIOp::create(builder, loc, resultCast, one); mlir::Value downResult = - builder.create(loc, resultCast, one); + mlir::arith::SubIOp::create(builder, loc, resultCast, one); // (a < b): r is inexact -- return r or ieee_next_down(r) - fir::IfOp ifOp2 = builder.create(loc, resultType, aLtB, - /*withElseRegion=*/true); + fir::IfOp ifOp2 = fir::IfOp::create(builder, loc, resultType, aLtB, + /*withElseRegion=*/true); builder.setInsertionPointToStart(&ifOp2.getThenRegion().front()); roundToZero = - builder.create(loc, roundToZeroBit, aIsPositive); + mlir::arith::AndIOp::create(builder, loc, roundToZeroBit, aIsPositive); roundAway = - builder.create(loc, roundAwayBit, aIsNegative); + mlir::arith::AndIOp::create(builder, loc, roundAwayBit, aIsNegative); mlir::Value roundDown = match(_FORTRAN_RUNTIME_IEEE_DOWN); mustAdjust = - builder.create(loc, roundToNearest, roundToZero); - mustAdjust = builder.create(loc, mustAdjust, roundAway); - mustAdjust = builder.create(loc, mustAdjust, roundDown); - adjustIfOp = builder.create(loc, resultType, mustAdjust, - /*withElseRegion=*/true); + mlir::arith::OrIOp::create(builder, loc, roundToNearest, roundToZero); + mustAdjust = mlir::arith::OrIOp::create(builder, loc, mustAdjust, roundAway); + mustAdjust = mlir::arith::OrIOp::create(builder, loc, mustAdjust, roundDown); + adjustIfOp = fir::IfOp::create(builder, loc, resultType, mustAdjust, + /*withElseRegion=*/true); builder.setInsertionPointToStart(&adjustIfOp.getThenRegion().front()); if (resultType.isF80()) r1 = fir::runtime::genNearest(builder, loc, r, builder.createBool(loc, false)); else - r1 = builder.create( - loc, resultType, - builder.create(loc, aIsNegative, upResult, - downResult)); - builder.create(loc, r1); + r1 = mlir::arith::BitcastOp::create( + builder, loc, resultType, + mlir::arith::SelectOp::create(builder, loc, aIsNegative, upResult, + downResult)); + fir::ResultOp::create(builder, loc, r1); builder.setInsertionPointToStart(&adjustIfOp.getElseRegion().front()); - builder.create(loc, r); + fir::ResultOp::create(builder, loc, r); builder.setInsertionPointAfter(adjustIfOp); - builder.create(loc, adjustIfOp.getResult(0)); + fir::ResultOp::create(builder, loc, adjustIfOp.getResult(0)); // (a > b): r is inexact -- return r or ieee_next_up(r) builder.setInsertionPointToStart(&ifOp2.getElseRegion().front()); roundToZero = - builder.create(loc, roundToZeroBit, aIsNegative); + mlir::arith::AndIOp::create(builder, loc, roundToZeroBit, aIsNegative); roundAway = - builder.create(loc, roundAwayBit, aIsPositive); + mlir::arith::AndIOp::create(builder, loc, roundAwayBit, aIsPositive); mlir::Value roundUp = match(_FORTRAN_RUNTIME_IEEE_UP); mustAdjust = - builder.create(loc, roundToNearest, roundToZero); - mustAdjust = builder.create(loc, mustAdjust, roundAway); - mustAdjust = builder.create(loc, mustAdjust, roundUp); - adjustIfOp = builder.create(loc, resultType, mustAdjust, - /*withElseRegion=*/true); + mlir::arith::OrIOp::create(builder, loc, roundToNearest, roundToZero); + mustAdjust = mlir::arith::OrIOp::create(builder, loc, mustAdjust, roundAway); + mustAdjust = mlir::arith::OrIOp::create(builder, loc, mustAdjust, roundUp); + adjustIfOp = fir::IfOp::create(builder, loc, resultType, mustAdjust, + /*withElseRegion=*/true); builder.setInsertionPointToStart(&adjustIfOp.getThenRegion().front()); if (resultType.isF80()) r1 = fir::runtime::genNearest(builder, loc, r, builder.createBool(loc, true)); else - r1 = builder.create( - loc, resultType, - builder.create(loc, aIsPositive, upResult, - downResult)); - builder.create(loc, r1); + r1 = mlir::arith::BitcastOp::create( + builder, loc, resultType, + mlir::arith::SelectOp::create(builder, loc, aIsPositive, upResult, + downResult)); + fir::ResultOp::create(builder, loc, r1); builder.setInsertionPointToStart(&adjustIfOp.getElseRegion().front()); - builder.create(loc, r); + fir::ResultOp::create(builder, loc, r); builder.setInsertionPointAfter(adjustIfOp); - builder.create(loc, adjustIfOp.getResult(0)); + fir::ResultOp::create(builder, loc, adjustIfOp.getResult(0)); // Generate exceptions for (a < b) and (a > b) branches. builder.setInsertionPointAfter(ifOp2); r = ifOp2.getResult(0); - fir::IfOp exceptIfOp1 = builder.create( - loc, genIsFPClass(i1Ty, r, infiniteTest), /*withElseRegion=*/true); + fir::IfOp exceptIfOp1 = + fir::IfOp::create(builder, loc, genIsFPClass(i1Ty, r, infiniteTest), + /*withElseRegion=*/true); builder.setInsertionPointToStart(&exceptIfOp1.getThenRegion().front()); genRaiseExcept(_FORTRAN_RUNTIME_IEEE_OVERFLOW | _FORTRAN_RUNTIME_IEEE_INEXACT); builder.setInsertionPointToStart(&exceptIfOp1.getElseRegion().front()); - fir::IfOp exceptIfOp2 = builder.create( - loc, genIsFPClass(i1Ty, r, subnormalTest | zeroTest), + fir::IfOp exceptIfOp2 = fir::IfOp::create( + builder, loc, genIsFPClass(i1Ty, r, subnormalTest | zeroTest), /*withElseRegion=*/true); builder.setInsertionPointToStart(&exceptIfOp2.getThenRegion().front()); genRaiseExcept(_FORTRAN_RUNTIME_IEEE_UNDERFLOW | @@ -5773,7 +5802,7 @@ mlir::Value IntrinsicLibrary::genIeeeReal(mlir::Type resultType, builder.setInsertionPointToStart(&exceptIfOp2.getElseRegion().front()); genRaiseExcept(_FORTRAN_RUNTIME_IEEE_INEXACT); builder.setInsertionPointAfter(exceptIfOp1); - builder.create(loc, ifOp2.getResult(0)); + fir::ResultOp::create(builder, loc, ifOp2.getResult(0)); builder.setInsertionPointAfter(ifOp1); return ifOp1.getResult(0); } @@ -5789,19 +5818,19 @@ mlir::Value IntrinsicLibrary::genIeeeRem(mlir::Type resultType, mlir::Value y = args[1]; if (mlir::dyn_cast(resultType).getWidth() < 32) { mlir::Type f32Ty = mlir::Float32Type::get(builder.getContext()); - x = builder.create(loc, f32Ty, x); - y = builder.create(loc, f32Ty, y); + x = fir::ConvertOp::create(builder, loc, f32Ty, x); + y = fir::ConvertOp::create(builder, loc, f32Ty, y); } else { - x = builder.create(loc, resultType, x); - y = builder.create(loc, resultType, y); + x = fir::ConvertOp::create(builder, loc, resultType, x); + y = fir::ConvertOp::create(builder, loc, resultType, y); } // remainder calls do not signal IEEE_UNDERFLOW. - mlir::Value underflow = builder.create( - loc, genIsFPClass(builder.getI1Type(), x, subnormalTest), + mlir::Value underflow = mlir::arith::AndIOp::create( + builder, 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); + return fir::ConvertOp::create(builder, loc, resultType, result); } // IEEE_RINT @@ -5817,19 +5846,19 @@ mlir::Value IntrinsicLibrary::genIeeeRint(mlir::Type resultType, mlir::func::FuncOp setRound = fir::factory::getLlvmSetRounding(builder); mlir::Value mode; if (isStaticallyPresent(args[1])) { - mode = builder.create(loc, getRound).getResult(0); + mode = fir::CallOp::create(builder, loc, getRound).getResult(0); genIeeeSetRoundingMode({args[1]}); } if (mlir::cast(resultType).getWidth() == 16) - a = builder.create( - loc, mlir::Float32Type::get(builder.getContext()), a); - mlir::Value result = builder.create( - loc, resultType, genRuntimeCall("nearbyint", a.getType(), a)); + a = fir::ConvertOp::create(builder, loc, + mlir::Float32Type::get(builder.getContext()), a); + mlir::Value result = fir::ConvertOp::create( + builder, loc, resultType, genRuntimeCall("nearbyint", a.getType(), a)); if (isStaticallyPresent(args[1])) { - builder.create(loc, setRound, mode); + fir::CallOp::create(builder, loc, setRound, mode); } else { - mlir::Value inexact = builder.create( - loc, mlir::arith::CmpFPredicate::ONE, args[0], result); + mlir::Value inexact = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::ONE, args[0], result); genRaiseExcept(_FORTRAN_RUNTIME_IEEE_INEXACT, inexact); } return result; @@ -5845,18 +5874,19 @@ void IntrinsicLibrary::genIeeeSetFlagOrHaltingMode( mlir::Type i1Ty = builder.getI1Type(); mlir::Type i32Ty = builder.getIntegerType(32); auto [fieldRef, ignore] = getFieldRef(builder, loc, getBase(args[0])); - mlir::Value field = builder.create(loc, fieldRef); + mlir::Value field = fir::LoadOp::create(builder, loc, fieldRef); mlir::Value except = fir::runtime::genMapExcept( - builder, loc, builder.create(loc, i32Ty, field)); - auto ifOp = builder.create( - loc, builder.create(loc, i1Ty, getBase(args[1])), + builder, loc, fir::ConvertOp::create(builder, loc, i32Ty, field)); + auto ifOp = fir::IfOp::create( + builder, loc, + fir::ConvertOp::create(builder, loc, i1Ty, getBase(args[1])), /*withElseRegion=*/true); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); (isFlag ? fir::runtime::genFeraiseexcept : fir::runtime::genFeenableexcept)( - builder, loc, builder.create(loc, i32Ty, except)); + builder, loc, fir::ConvertOp::create(builder, loc, i32Ty, except)); builder.setInsertionPointToStart(&ifOp.getElseRegion().front()); (isFlag ? fir::runtime::genFeclearexcept : fir::runtime::genFedisableexcept)( - builder, loc, builder.create(loc, i32Ty, except)); + builder, loc, fir::ConvertOp::create(builder, loc, i32Ty, except)); builder.setInsertionPointAfter(ifOp); } @@ -5873,7 +5903,7 @@ void IntrinsicLibrary::genIeeeSetRoundingMode( checkRadix(builder, loc, fir::getBase(args[1]), "ieee_set_rounding_mode"); auto [fieldRef, fieldTy] = getFieldRef(builder, loc, fir::getBase(args[0])); mlir::func::FuncOp setRound = fir::factory::getLlvmSetRounding(builder); - mlir::Value mode = builder.create(loc, fieldRef); + mlir::Value mode = fir::LoadOp::create(builder, loc, fieldRef); static_assert( _FORTRAN_RUNTIME_IEEE_TO_ZERO >= 0 && _FORTRAN_RUNTIME_IEEE_TO_ZERO <= 3 && @@ -5881,28 +5911,28 @@ void IntrinsicLibrary::genIeeeSetRoundingMode( _FORTRAN_RUNTIME_IEEE_NEAREST <= 3 && _FORTRAN_RUNTIME_IEEE_UP >= 0 && _FORTRAN_RUNTIME_IEEE_UP <= 3 && _FORTRAN_RUNTIME_IEEE_DOWN >= 0 && _FORTRAN_RUNTIME_IEEE_DOWN <= 3 && "unexpected rounding mode mapping"); - mlir::Value mask = builder.create( - loc, builder.createAllOnesInteger(loc, fieldTy), + mlir::Value mask = mlir::arith::ShLIOp::create( + builder, loc, builder.createAllOnesInteger(loc, fieldTy), builder.createIntegerConstant(loc, fieldTy, 2)); - mlir::Value modeIsSupported = builder.create( - loc, mlir::arith::CmpIPredicate::eq, - builder.create(loc, mode, mask), + mlir::Value modeIsSupported = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, + mlir::arith::AndIOp::create(builder, loc, mode, mask), builder.createIntegerConstant(loc, fieldTy, 0)); mlir::Value nearest = builder.createIntegerConstant( loc, fieldTy, _FORTRAN_RUNTIME_IEEE_NEAREST); - mode = builder.create(loc, modeIsSupported, mode, - nearest); - mode = builder.create( - loc, setRound.getFunctionType().getInput(0), mode); - builder.create(loc, setRound, mode); + mode = mlir::arith::SelectOp::create(builder, loc, modeIsSupported, mode, + nearest); + mode = fir::ConvertOp::create(builder, loc, + setRound.getFunctionType().getInput(0), mode); + fir::CallOp::create(builder, loc, setRound, mode); } // IEEE_SET_UNDERFLOW_MODE void IntrinsicLibrary::genIeeeSetUnderflowMode( llvm::ArrayRef args) { assert(args.size() == 1); - mlir::Value gradual = builder.create(loc, builder.getI1Type(), - getBase(args[0])); + mlir::Value gradual = fir::ConvertOp::create( + builder, loc, builder.getI1Type(), getBase(args[0])); fir::runtime::genSetUnderflowMode(builder, loc, {gradual}); } @@ -5916,9 +5946,9 @@ IntrinsicLibrary::genIeeeSignalingCompare(mlir::Type resultType, assert(args.size() == 2); mlir::Value hasNaNOp = genIeeeUnordered(mlir::Type{}, args); mlir::Value res = - builder.create(loc, pred, args[0], args[1]); + mlir::arith::CmpFOp::create(builder, loc, pred, args[0], args[1]); genRaiseExcept(_FORTRAN_RUNTIME_IEEE_INVALID, hasNaNOp); - return builder.create(loc, resultType, res); + return fir::ConvertOp::create(builder, loc, resultType, res); } // IEEE_SIGNBIT @@ -5937,9 +5967,9 @@ mlir::Value IntrinsicLibrary::genIeeeSignbit(mlir::Type resultType, } mlir::Type intType = builder.getIntegerType(bitWidth); mlir::Value intVal = - builder.create(loc, intType, realVal); + mlir::arith::BitcastOp::create(builder, loc, intType, realVal); mlir::Value shift = builder.createIntegerConstant(loc, intType, bitWidth - 1); - mlir::Value sign = builder.create(loc, intVal, shift); + mlir::Value sign = mlir::arith::ShRUIOp::create(builder, loc, intVal, shift); return builder.createConvert(loc, resultType, sign); } @@ -5952,21 +5982,21 @@ IntrinsicLibrary::genIeeeSupportFlag(mlir::Type resultType, mlir::Type i1Ty = builder.getI1Type(); mlir::Type i32Ty = builder.getIntegerType(32); auto [fieldRef, fieldTy] = getFieldRef(builder, loc, getBase(args[0])); - mlir::Value flag = builder.create(loc, fieldRef); + mlir::Value flag = fir::LoadOp::create(builder, loc, fieldRef); mlir::Value standardFlagMask = builder.createIntegerConstant( loc, fieldTy, _FORTRAN_RUNTIME_IEEE_INVALID | _FORTRAN_RUNTIME_IEEE_DIVIDE_BY_ZERO | _FORTRAN_RUNTIME_IEEE_OVERFLOW | _FORTRAN_RUNTIME_IEEE_UNDERFLOW | _FORTRAN_RUNTIME_IEEE_INEXACT); - mlir::Value isStandardFlag = builder.create( - loc, mlir::arith::CmpIPredicate::ne, - builder.create(loc, flag, standardFlagMask), + mlir::Value isStandardFlag = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::ne, + mlir::arith::AndIOp::create(builder, loc, flag, standardFlagMask), builder.createIntegerConstant(loc, fieldTy, 0)); - fir::IfOp ifOp = builder.create(loc, i1Ty, isStandardFlag, - /*withElseRegion=*/true); + fir::IfOp ifOp = fir::IfOp::create(builder, loc, i1Ty, isStandardFlag, + /*withElseRegion=*/true); // Standard flags are supported. builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); - builder.create(loc, builder.createBool(loc, true)); + fir::ResultOp::create(builder, loc, builder.createBool(loc, true)); // TargetCharacteristics information for the nonstandard ieee_denorm flag // is not available here. So use a runtime check restricted to possibly @@ -5990,17 +6020,17 @@ IntrinsicLibrary::genIeeeSupportFlag(mlir::Type resultType, } } if (mayBeSupported) { - mlir::Value isDenorm = builder.create( - loc, mlir::arith::CmpIPredicate::eq, flag, + mlir::Value isDenorm = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, flag, builder.createIntegerConstant(loc, fieldTy, _FORTRAN_RUNTIME_IEEE_DENORM)); - mlir::Value result = builder.create( - loc, isDenorm, + mlir::Value result = mlir::arith::AndIOp::create( + builder, loc, isDenorm, fir::runtime::genSupportHalting( - builder, loc, builder.create(loc, i32Ty, flag))); - builder.create(loc, result); + builder, loc, fir::ConvertOp::create(builder, loc, i32Ty, flag))); + fir::ResultOp::create(builder, loc, result); } else { - builder.create(loc, builder.createBool(loc, false)); + fir::ResultOp::create(builder, loc, builder.createBool(loc, false)); } builder.setInsertionPointAfter(ifOp); return builder.createConvert(loc, resultType, ifOp.getResult(0)); @@ -6015,11 +6045,11 @@ fir::ExtendedValue IntrinsicLibrary::genIeeeSupportHalting( assert(args.size() == 1); mlir::Type i32Ty = builder.getIntegerType(32); auto [fieldRef, ignore] = getFieldRef(builder, loc, getBase(args[0])); - mlir::Value field = builder.create(loc, fieldRef); + mlir::Value field = fir::LoadOp::create(builder, loc, fieldRef); return builder.createConvert( loc, resultType, fir::runtime::genSupportHalting( - builder, loc, builder.create(loc, i32Ty, field))); + builder, loc, fir::ConvertOp::create(builder, loc, i32Ty, field))); } // IEEE_SUPPORT_ROUNDING @@ -6036,16 +6066,16 @@ fir::ExtendedValue IntrinsicLibrary::genIeeeSupportRounding( // 4 - to nearest, ties away from zero [not supported] assert(args.size() == 1 || args.size() == 2); auto [fieldRef, fieldTy] = getFieldRef(builder, loc, getBase(args[0])); - mlir::Value mode = builder.create(loc, fieldRef); - mlir::Value lbOk = builder.create( - loc, mlir::arith::CmpIPredicate::sge, mode, + mlir::Value mode = fir::LoadOp::create(builder, loc, fieldRef); + mlir::Value lbOk = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::sge, mode, builder.createIntegerConstant(loc, fieldTy, _FORTRAN_RUNTIME_IEEE_TO_ZERO)); - mlir::Value ubOk = builder.create( - loc, mlir::arith::CmpIPredicate::sle, mode, + mlir::Value ubOk = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::sle, mode, builder.createIntegerConstant(loc, fieldTy, _FORTRAN_RUNTIME_IEEE_DOWN)); return builder.createConvert( - loc, resultType, builder.create(loc, lbOk, ubOk)); + loc, resultType, mlir::arith::AndIOp::create(builder, loc, lbOk, ubOk)); } // IEEE_SUPPORT_STANDARD @@ -6069,15 +6099,15 @@ IntrinsicLibrary::genIeeeUnordered(mlir::Type resultType, // If there is no result type return an i1 result. assert(args.size() == 2); if (args[0].getType() == args[1].getType()) { - mlir::Value res = builder.create( - loc, mlir::arith::CmpFPredicate::UNO, args[0], args[1]); + mlir::Value res = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::UNO, args[0], args[1]); return resultType ? builder.createConvert(loc, resultType, res) : res; } assert(resultType && "expecting a (mixed arg type) unordered result type"); mlir::Type i1Ty = builder.getI1Type(); mlir::Value xIsNan = genIsFPClass(i1Ty, args[0], nanTest); mlir::Value yIsNan = genIsFPClass(i1Ty, args[1], nanTest); - mlir::Value res = builder.create(loc, xIsNan, yIsNan); + mlir::Value res = mlir::arith::OrIOp::create(builder, loc, xIsNan, yIsNan); return builder.createConvert(loc, resultType, res); } @@ -6202,22 +6232,22 @@ mlir::Value IntrinsicLibrary::genIeeeValue(mlir::Type resultType, mlir::Value which; if (args.size() == 2) { // user call auto [index, ignore] = getFieldRef(builder, loc, args[1]); - which = builder.create(loc, index); + which = fir::LoadOp::create(builder, loc, index); } else { // compiler generated call which = args[0]; } - mlir::Value bits = builder.create( - loc, - builder.create( - loc, builder.getRefType(valueTy), - builder.create(loc, builder.getRefType(tableTy), - builder.getSymbolRefAttr(tableName)), + mlir::Value bits = fir::LoadOp::create( + builder, loc, + fir::CoordinateOp::create( + builder, loc, builder.getRefType(valueTy), + fir::AddrOfOp::create(builder, loc, builder.getRefType(tableTy), + builder.getSymbolRefAttr(tableName)), which)); if (bitWidth > 64) - bits = builder.create( - loc, builder.createConvert(loc, intType, bits), + bits = mlir::arith::ShLIOp::create( + builder, loc, builder.createConvert(loc, intType, bits), builder.createIntegerConstant(loc, intType, bitWidth - 64)); - return builder.create(loc, realType, bits); + return mlir::arith::BitcastOp::create(builder, loc, realType, bits); } // IEOR @@ -6259,13 +6289,14 @@ IntrinsicLibrary::genIndex(mlir::Type resultType, builder.getContext(), builder.getKindMap().defaultLogicalKind()); mlir::Value temp = builder.createTemporary(loc, logTy); mlir::Value castb = builder.createConvert(loc, logTy, b); - builder.create(loc, castb, temp); + fir::StoreOp::create(builder, loc, castb, temp); return builder.createBox(loc, temp); }; - mlir::Value backOpt = isStaticallyAbsent(args, 2) - ? builder.create( - loc, fir::BoxType::get(builder.getI1Type())) - : makeRefThenEmbox(fir::getBase(args[2])); + mlir::Value backOpt = + isStaticallyAbsent(args, 2) + ? fir::AbsentOp::create(builder, loc, + fir::BoxType::get(builder.getI1Type())) + : makeRefThenEmbox(fir::getBase(args[2])); mlir::Value kindVal = isStaticallyAbsent(args, 3) ? builder.createIntegerConstant( loc, builder.getIndexType(), @@ -6314,8 +6345,8 @@ mlir::Value IntrinsicLibrary::genIsIostatValue(mlir::Type resultType, llvm::ArrayRef args) { assert(args.size() == 1); - return builder.create( - loc, mlir::arith::CmpIPredicate::eq, args[0], + return mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, args[0], builder.createIntegerConstant(loc, args[0].getType(), value)); } @@ -6342,16 +6373,16 @@ mlir::Value IntrinsicLibrary::genIshft(mlir::Type resultType, mlir::Value word = args[0]; if (word.getType().isUnsignedInteger()) word = builder.createConvert(loc, signlessType, word); - auto left = builder.create(loc, word, absShift); - auto right = builder.create(loc, word, absShift); - auto shiftIsLarge = builder.create( - loc, mlir::arith::CmpIPredicate::sge, absShift, bitSize); - auto shiftIsNegative = builder.create( - loc, mlir::arith::CmpIPredicate::slt, shift, zero); + auto left = mlir::arith::ShLIOp::create(builder, loc, word, absShift); + auto right = mlir::arith::ShRUIOp::create(builder, loc, word, absShift); + auto shiftIsLarge = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::sge, absShift, bitSize); + auto shiftIsNegative = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::slt, shift, zero); auto sel = - builder.create(loc, shiftIsNegative, right, left); + mlir::arith::SelectOp::create(builder, loc, shiftIsNegative, right, left); mlir::Value result = - builder.create(loc, shiftIsLarge, zero, sel); + mlir::arith::SelectOp::create(builder, loc, shiftIsLarge, zero, sel); if (resultType.isUnsignedInteger()) return builder.createConvert(loc, resultType, result); return result; @@ -6392,42 +6423,42 @@ mlir::Value IntrinsicLibrary::genIshftc(mlir::Type resultType, mlir::Value zero = builder.createIntegerConstant(loc, signlessType, 0); mlir::Value ones = builder.createAllOnesInteger(loc, signlessType); mlir::Value absShift = genAbs(signlessType, {shift}); - auto elseSize = builder.create(loc, size, absShift); - auto shiftIsZero = builder.create( - loc, mlir::arith::CmpIPredicate::eq, shift, zero); - auto shiftEqualsSize = builder.create( - loc, mlir::arith::CmpIPredicate::eq, absShift, size); + auto elseSize = mlir::arith::SubIOp::create(builder, loc, size, absShift); + auto shiftIsZero = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, shift, zero); + auto shiftEqualsSize = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, absShift, size); auto shiftIsNop = - builder.create(loc, shiftIsZero, shiftEqualsSize); - auto shiftIsPositive = builder.create( - loc, mlir::arith::CmpIPredicate::sgt, shift, zero); - auto leftSize = builder.create(loc, shiftIsPositive, - absShift, elseSize); - auto rightSize = builder.create(loc, shiftIsPositive, - elseSize, absShift); - auto hasUnchanged = builder.create( - loc, mlir::arith::CmpIPredicate::ne, size, bitSize); - auto unchangedTmp1 = builder.create(loc, word, size); + mlir::arith::OrIOp::create(builder, loc, shiftIsZero, shiftEqualsSize); + auto shiftIsPositive = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::sgt, shift, zero); + auto leftSize = mlir::arith::SelectOp::create(builder, loc, shiftIsPositive, + absShift, elseSize); + auto rightSize = mlir::arith::SelectOp::create(builder, loc, shiftIsPositive, + elseSize, absShift); + auto hasUnchanged = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::ne, size, bitSize); + auto unchangedTmp1 = mlir::arith::ShRUIOp::create(builder, loc, word, size); auto unchangedTmp2 = - builder.create(loc, unchangedTmp1, size); - auto unchanged = builder.create(loc, hasUnchanged, - unchangedTmp2, zero); + mlir::arith::ShLIOp::create(builder, loc, unchangedTmp1, size); + auto unchanged = mlir::arith::SelectOp::create(builder, loc, hasUnchanged, + unchangedTmp2, zero); auto leftMaskShift = - builder.create(loc, bitSize, leftSize); + mlir::arith::SubIOp::create(builder, loc, bitSize, leftSize); auto leftMask = - builder.create(loc, ones, leftMaskShift); - auto leftTmp = builder.create(loc, word, rightSize); - auto left = builder.create(loc, leftTmp, leftMask); + mlir::arith::ShRUIOp::create(builder, loc, ones, leftMaskShift); + auto leftTmp = mlir::arith::ShRUIOp::create(builder, loc, word, rightSize); + auto left = mlir::arith::AndIOp::create(builder, loc, leftTmp, leftMask); auto rightMaskShift = - builder.create(loc, bitSize, rightSize); + mlir::arith::SubIOp::create(builder, loc, bitSize, rightSize); auto rightMask = - builder.create(loc, ones, rightMaskShift); - auto rightTmp = builder.create(loc, word, rightMask); - auto right = builder.create(loc, rightTmp, leftSize); - auto resTmp = builder.create(loc, unchanged, left); - auto res = builder.create(loc, resTmp, right); + mlir::arith::ShRUIOp::create(builder, loc, ones, rightMaskShift); + auto rightTmp = mlir::arith::AndIOp::create(builder, loc, word, rightMask); + auto right = mlir::arith::ShLIOp::create(builder, loc, rightTmp, leftSize); + auto resTmp = mlir::arith::OrIOp::create(builder, loc, unchanged, left); + auto res = mlir::arith::OrIOp::create(builder, loc, resTmp, right); mlir::Value result = - builder.create(loc, shiftIsNop, word, res); + mlir::arith::SelectOp::create(builder, loc, shiftIsNop, word, res); if (resultType.isUnsignedInteger()) return builder.createConvert(loc, resultType, result); return result; @@ -6439,7 +6470,7 @@ mlir::Value IntrinsicLibrary::genLeadz(mlir::Type resultType, assert(args.size() == 1); mlir::Value result = - builder.create(loc, args); + mlir::math::CountLeadingZerosOp::create(builder, loc, args); return builder.createConvert(loc, resultType, result); } @@ -6507,18 +6538,18 @@ IntrinsicLibrary::genLoc(mlir::Type resultType, // created when preparing the argument cases, but the box can be safely be // used for all those cases and the address will be null if absent. mlir::Value isPresent = - builder.create(loc, builder.getI1Type(), box); + fir::IsPresentOp::create(builder, loc, builder.getI1Type(), box); return builder .genIfOp(loc, {resultType}, isPresent, /*withElseRegion=*/true) .genThen([&]() { mlir::Value argAddr = getAddrFromBox(builder, loc, args[0], isFunc); mlir::Value cast = builder.createConvert(loc, resultType, argAddr); - builder.create(loc, cast); + fir::ResultOp::create(builder, loc, cast); }) .genElse([&]() { mlir::Value zero = builder.createIntegerConstant(loc, resultType, 0); - builder.create(loc, zero); + fir::ResultOp::create(builder, loc, zero); }) .getResults()[0]; } @@ -6551,12 +6582,12 @@ mlir::Value IntrinsicLibrary::genMask(mlir::Type resultType, // non-deterministic result. Other compilers don't produce a consistent result // in this case either, so we choose the most efficient implementation. mlir::Value shift = - builder.create(loc, bitSize, bitsToSet); - mlir::Value shifted = builder.create(loc, ones, shift); - mlir::Value isZero = builder.create( - loc, mlir::arith::CmpIPredicate::eq, bitsToSet, zero); + mlir::arith::SubIOp::create(builder, loc, bitSize, bitsToSet); + mlir::Value shifted = Shift::create(builder, loc, ones, shift); + mlir::Value isZero = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, bitsToSet, zero); mlir::Value result = - builder.create(loc, isZero, zero, shifted); + mlir::arith::SelectOp::create(builder, loc, isZero, zero, shifted); if (resultType.isUnsignedInteger()) return builder.createConvert(loc, resultType, result); return result; @@ -6574,8 +6605,8 @@ IntrinsicLibrary::genMatchAllSync(mlir::Type resultType, mlir::Value arg1 = args[1]; if (arg1.getType().isF32() || arg1.getType().isF64()) - arg1 = builder.create( - loc, is32 ? builder.getI32Type() : builder.getI64Type(), arg1); + arg1 = fir::ConvertOp::create( + builder, loc, is32 ? builder.getI32Type() : builder.getI64Type(), arg1); mlir::Type retTy = mlir::LLVM::LLVMStructType::getLiteral(context, {resultType, i1Ty}); @@ -6584,10 +6615,10 @@ IntrinsicLibrary::genMatchAllSync(mlir::Type resultType, .create(loc, retTy, args[0], arg1, mlir::NVVM::MatchSyncKind::all) .getResult(); - auto value = builder.create(loc, match, 0); - auto pred = builder.create(loc, match, 1); - auto conv = builder.create(loc, resultType, pred); - builder.create(loc, conv, args[2]); + auto value = mlir::LLVM::ExtractValueOp::create(builder, loc, match, 0); + auto pred = mlir::LLVM::ExtractValueOp::create(builder, loc, match, 1); + auto conv = mlir::LLVM::ZExtOp::create(builder, loc, resultType, pred); + fir::StoreOp::create(builder, loc, conv, args[2]); return value; } @@ -6597,14 +6628,14 @@ mlir::Value IntrinsicLibrary::genVoteSync(mlir::Type resultType, llvm::ArrayRef args) { assert(args.size() == 2); mlir::Value arg1 = - builder.create(loc, builder.getI1Type(), args[1]); + fir::ConvertOp::create(builder, loc, builder.getI1Type(), args[1]); mlir::Type resTy = kind == mlir::NVVM::VoteSyncKind::ballot ? builder.getI32Type() : builder.getI1Type(); auto voteRes = - builder.create(loc, resTy, args[0], arg1, kind) + mlir::NVVM::VoteSyncOp::create(builder, loc, resTy, args[0], arg1, kind) .getResult(); - return builder.create(loc, resultType, voteRes); + return fir::ConvertOp::create(builder, loc, resultType, voteRes); } // MATCH_ANY_SYNC @@ -6616,8 +6647,8 @@ IntrinsicLibrary::genMatchAnySync(mlir::Type resultType, mlir::Value arg1 = args[1]; if (arg1.getType().isF32() || arg1.getType().isF64()) - arg1 = builder.create( - loc, is32 ? builder.getI32Type() : builder.getI64Type(), arg1); + arg1 = fir::ConvertOp::create( + builder, loc, is32 ? builder.getI32Type() : builder.getI64Type(), arg1); return builder .create(loc, resultType, args[0], arg1, @@ -6701,10 +6732,10 @@ IntrinsicLibrary::genMerge(mlir::Type, mlir::Value other) -> mlir::Value { mlir::Type otherType = other.getType(); if (mlir::isa(otherType)) - return builder.create(loc, otherType, polymorphic, - /*shape*/ mlir::Value{}, - /*slice=*/mlir::Value{}); - return builder.create(loc, otherType, polymorphic); + return fir::ReboxOp::create(builder, loc, otherType, polymorphic, + /*shape*/ mlir::Value{}, + /*slice=*/mlir::Value{}); + return fir::BoxAddrOp::create(builder, loc, otherType, polymorphic); }; if (fir::isPolymorphicType(tsource.getType()) && !fir::isPolymorphicType(fsource.getType())) { @@ -6720,8 +6751,8 @@ IntrinsicLibrary::genMerge(mlir::Type, // fulfill mlir::SelectOp constraint that the MLIR types must be the same. fsourceCast = builder.createConvert(loc, tsource.getType(), fsource); } - auto rslt = builder.create(loc, mask, tsourceCast, - fsourceCast); + auto rslt = mlir::arith::SelectOp::create(builder, loc, mask, tsourceCast, + fsourceCast); if (isCharRslt) { // Need a CharBoxValue for character results const fir::CharBoxValue *charBox = args[0].getCharBox(); @@ -6762,7 +6793,7 @@ mlir::Value IntrinsicLibrary::genMod(mlir::Type resultType, args[0], args[1]); } if (mlir::isa(resultType)) - return builder.create(loc, args[0], args[1]); + return mlir::arith::RemSIOp::create(builder, loc, args[0], args[1]); // Use runtime. return builder.createConvert( @@ -6792,19 +6823,19 @@ mlir::Value IntrinsicLibrary::genModulo(mlir::Type resultType, } if (mlir::isa(resultType)) { auto remainder = - builder.create(loc, args[0], args[1]); - auto argXor = builder.create(loc, args[0], args[1]); + mlir::arith::RemSIOp::create(builder, loc, args[0], args[1]); + auto argXor = mlir::arith::XOrIOp::create(builder, loc, args[0], args[1]); mlir::Value zero = builder.createIntegerConstant(loc, argXor.getType(), 0); - auto argSignDifferent = builder.create( - loc, mlir::arith::CmpIPredicate::slt, argXor, zero); - auto remainderIsNotZero = builder.create( - loc, mlir::arith::CmpIPredicate::ne, remainder, zero); - auto mustAddP = builder.create(loc, remainderIsNotZero, - argSignDifferent); + auto argSignDifferent = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::slt, argXor, zero); + auto remainderIsNotZero = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::ne, remainder, zero); + auto mustAddP = mlir::arith::AndIOp::create( + builder, loc, remainderIsNotZero, argSignDifferent); auto remPlusP = - builder.create(loc, remainder, args[1]); - return builder.create(loc, mustAddP, remPlusP, - remainder); + mlir::arith::AddIOp::create(builder, loc, remainder, args[1]); + return mlir::arith::SelectOp::create(builder, loc, mustAddP, remPlusP, + remainder); } auto fastMathFlags = builder.getFastMathFlags(); @@ -6817,21 +6848,21 @@ mlir::Value IntrinsicLibrary::genModulo(mlir::Type resultType, loc, resultType, fir::runtime::genModulo(builder, loc, args[0], args[1])); - auto remainder = builder.create(loc, args[0], args[1]); + auto remainder = mlir::arith::RemFOp::create(builder, loc, args[0], args[1]); mlir::Value zero = builder.createRealZeroConstant(loc, remainder.getType()); - auto remainderIsNotZero = builder.create( - loc, mlir::arith::CmpFPredicate::UNE, remainder, zero); - auto aLessThanZero = builder.create( - loc, mlir::arith::CmpFPredicate::OLT, args[0], zero); - auto pLessThanZero = builder.create( - loc, mlir::arith::CmpFPredicate::OLT, args[1], zero); + auto remainderIsNotZero = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::UNE, remainder, zero); + auto aLessThanZero = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::OLT, args[0], zero); + auto pLessThanZero = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::OLT, args[1], zero); auto argSignDifferent = - builder.create(loc, aLessThanZero, pLessThanZero); - auto mustAddP = builder.create(loc, remainderIsNotZero, - argSignDifferent); - auto remPlusP = builder.create(loc, remainder, args[1]); - return builder.create(loc, mustAddP, remPlusP, - remainder); + mlir::arith::XOrIOp::create(builder, loc, aLessThanZero, pLessThanZero); + auto mustAddP = mlir::arith::AndIOp::create(builder, loc, remainderIsNotZero, + argSignDifferent); + auto remPlusP = mlir::arith::AddFOp::create(builder, loc, remainder, args[1]); + return mlir::arith::SelectOp::create(builder, loc, mustAddP, remPlusP, + remainder); } void IntrinsicLibrary::genMoveAlloc(llvm::ArrayRef args) { @@ -6846,7 +6877,7 @@ void IntrinsicLibrary::genMoveAlloc(llvm::ArrayRef args) { mlir::Value errBox = isStaticallyPresent(errMsg) ? fir::getBase(errMsg) - : builder.create(loc, boxNoneTy).getResult(); + : fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); const fir::MutableBoxValue *fromBox = from.getBoxOf(); const fir::MutableBoxValue *toBox = to.getBoxOf(); @@ -6903,33 +6934,34 @@ void IntrinsicLibrary::genMvbits(llvm::ArrayRef args) { mlir::Type toType{fir::dyn_cast_ptrEleTy(toAddr.getType())}; assert(toType.getIntOrFloatBitWidth() == fromType.getIntOrFloatBitWidth() && "mismatched mvbits types"); - auto to = builder.create(loc, signlessType, toAddr); + auto to = fir::LoadOp::create(builder, loc, signlessType, toAddr); mlir::Value topos = builder.createConvert(loc, signlessType, unbox(args[4])); mlir::Value zero = builder.createIntegerConstant(loc, signlessType, 0); mlir::Value ones = builder.createAllOnesInteger(loc, signlessType); mlir::Value bitSize = builder.createIntegerConstant( loc, signlessType, mlir::cast(signlessType).getWidth()); - auto shiftCount = builder.create(loc, bitSize, len); - auto mask = builder.create(loc, ones, shiftCount); - auto unchangedTmp1 = builder.create(loc, mask, topos); + auto shiftCount = mlir::arith::SubIOp::create(builder, loc, bitSize, len); + auto mask = mlir::arith::ShRUIOp::create(builder, loc, ones, shiftCount); + auto unchangedTmp1 = mlir::arith::ShLIOp::create(builder, loc, mask, topos); auto unchangedTmp2 = - builder.create(loc, unchangedTmp1, ones); - auto unchanged = builder.create(loc, unchangedTmp2, to); + mlir::arith::XOrIOp::create(builder, loc, unchangedTmp1, ones); + auto unchanged = mlir::arith::AndIOp::create(builder, loc, unchangedTmp2, to); if (fromType.isUnsignedInteger()) from = builder.createConvert(loc, signlessType, from); - auto frombitsTmp1 = builder.create(loc, from, frompos); + auto frombitsTmp1 = mlir::arith::ShRUIOp::create(builder, loc, from, frompos); auto frombitsTmp2 = - builder.create(loc, frombitsTmp1, mask); - auto frombits = builder.create(loc, frombitsTmp2, topos); - auto resTmp = builder.create(loc, unchanged, frombits); - auto lenIsZero = builder.create( - loc, mlir::arith::CmpIPredicate::eq, len, zero); + mlir::arith::AndIOp::create(builder, loc, frombitsTmp1, mask); + auto frombits = + mlir::arith::ShLIOp::create(builder, loc, frombitsTmp2, topos); + auto resTmp = mlir::arith::OrIOp::create(builder, loc, unchanged, frombits); + auto lenIsZero = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, len, zero); mlir::Value res = - builder.create(loc, lenIsZero, to, resTmp); + mlir::arith::SelectOp::create(builder, loc, lenIsZero, to, resTmp); if (toType.isUnsignedInteger()) res = builder.createConvert(loc, toType, res); - builder.create(loc, res, toAddr); + fir::StoreOp::create(builder, loc, res, toAddr); } // NEAREST, IEEE_NEXT_AFTER, IEEE_NEXT_DOWN, IEEE_NEXT_UP @@ -6971,7 +7003,7 @@ mlir::Value IntrinsicLibrary::genNearest(mlir::Type resultType, // If isNan(Y), set X to a qNaN that will propagate to the resultIsX result. mlir::Value qNan = genQNan(xType); mlir::Value isFPClass = genIsFPClass(i1Ty, args[1], nanTest); - x = builder.create(loc, isFPClass, qNan, x); + x = mlir::arith::SelectOp::create(builder, loc, isFPClass, qNan, x); } mlir::Value resultIsX = genIsFPClass(i1Ty, x, nanTest); mlir::Type intType = builder.getIntegerType(xBitWidth); @@ -6982,15 +7014,15 @@ mlir::Value IntrinsicLibrary::genNearest(mlir::Type resultType, if constexpr (proc == NearestProc::Nearest) { // Arg S must not be zero. fir::IfOp ifOp = - builder.create(loc, genIsFPClass(i1Ty, args[1], zeroTest), - /*withElseRegion=*/false); + fir::IfOp::create(builder, loc, genIsFPClass(i1Ty, args[1], zeroTest), + /*withElseRegion=*/false); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); fir::runtime::genReportFatalUserError( builder, loc, "intrinsic nearest S argument is zero"); builder.setInsertionPointAfter(ifOp); mlir::Value sSign = IntrinsicLibrary::genIeeeSignbit(intType, {args[1]}); - valueUp = builder.create( - loc, mlir::arith::CmpIPredicate::ne, sSign, one); + valueUp = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::ne, sSign, one); } else if constexpr (proc == NearestProc::NextAfter) { // Convert X and Y to a common type to allow comparison. Direct conversions // between kinds 2, 3, 10, and 16 are not all supported. These conversions @@ -7011,58 +7043,58 @@ mlir::Value IntrinsicLibrary::genNearest(mlir::Type resultType, if (xBitWidth > 32 && xBitWidth > yBitWidth) y = builder.createConvert(loc, xType, y); } - resultIsX = builder.create( - loc, resultIsX, - builder.create( - loc, mlir::arith::CmpFPredicate::OEQ, x1, y)); - valueUp = builder.create( - loc, mlir::arith::CmpFPredicate::OLT, x1, y); + resultIsX = mlir::arith::OrIOp::create( + builder, loc, resultIsX, + mlir::arith::CmpFOp::create(builder, loc, + mlir::arith::CmpFPredicate::OEQ, x1, y)); + valueUp = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::OLT, x1, y); } else if constexpr (proc == NearestProc::NextDown) { valueUp = builder.createBool(loc, false); } else if constexpr (proc == NearestProc::NextUp) { valueUp = builder.createBool(loc, true); } - mlir::Value magnitudeUp = builder.create( - loc, mlir::arith::CmpIPredicate::ne, valueUp, + mlir::Value magnitudeUp = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::ne, valueUp, IntrinsicLibrary::genIeeeSignbit(i1Ty, {args[0]})); - resultIsX = builder.create( - loc, resultIsX, - builder.create( - loc, genIsFPClass(i1Ty, x, infiniteTest), magnitudeUp)); + resultIsX = mlir::arith::OrIOp::create( + builder, loc, resultIsX, + mlir::arith::AndIOp::create( + builder, loc, genIsFPClass(i1Ty, x, infiniteTest), magnitudeUp)); // Result is X. (For ieee_next_after with isNan(Y), X has been set to a NaN.) - fir::IfOp outerIfOp = builder.create(loc, resultType, resultIsX, - /*withElseRegion=*/true); + fir::IfOp outerIfOp = fir::IfOp::create(builder, loc, resultType, resultIsX, + /*withElseRegion=*/true); builder.setInsertionPointToStart(&outerIfOp.getThenRegion().front()); if constexpr (proc == NearestProc::NextDown || proc == NearestProc::NextUp) genRaiseExcept(_FORTRAN_RUNTIME_IEEE_INVALID, genIsFPClass(i1Ty, x, snanTest)); - builder.create(loc, x); + fir::ResultOp::create(builder, loc, x); // Result is minPositiveSubnormal or minNegativeSubnormal. (X is zero.) builder.setInsertionPointToStart(&outerIfOp.getElseRegion().front()); - mlir::Value resultIsMinSubnormal = builder.create( - loc, mlir::arith::CmpFPredicate::OEQ, x, + mlir::Value resultIsMinSubnormal = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::OEQ, x, builder.createRealZeroConstant(loc, xType)); fir::IfOp innerIfOp = - builder.create(loc, resultType, resultIsMinSubnormal, - /*withElseRegion=*/true); + fir::IfOp::create(builder, loc, resultType, resultIsMinSubnormal, + /*withElseRegion=*/true); builder.setInsertionPointToStart(&innerIfOp.getThenRegion().front()); mlir::Value minPositiveSubnormal = - builder.create(loc, resultType, one); - mlir::Value minNegativeSubnormal = builder.create( - loc, resultType, - builder.create( - loc, intType, + mlir::arith::BitcastOp::create(builder, loc, resultType, one); + mlir::Value minNegativeSubnormal = mlir::arith::BitcastOp::create( + builder, loc, resultType, + mlir::arith::ConstantOp::create( + builder, loc, intType, builder.getIntegerAttr( intType, llvm::APInt::getBitsSetWithWrap( xBitWidth, /*lo=*/xBitWidth - 1, /*hi=*/1)))); - mlir::Value result = builder.create( - loc, valueUp, minPositiveSubnormal, minNegativeSubnormal); + mlir::Value result = mlir::arith::SelectOp::create( + builder, loc, valueUp, minPositiveSubnormal, minNegativeSubnormal); if constexpr (proc == NearestProc::Nearest || proc == NearestProc::NextAfter) genRaiseExcept(_FORTRAN_RUNTIME_IEEE_UNDERFLOW | _FORTRAN_RUNTIME_IEEE_INEXACT); - builder.create(loc, result); + fir::ResultOp::create(builder, loc, result); // Result is (X + minPositiveSubnormal) or (X - minPositiveSubnormal). builder.setInsertionPointToStart(&innerIfOp.getElseRegion().front()); @@ -7088,15 +7120,15 @@ mlir::Value IntrinsicLibrary::genNearest(mlir::Type resultType, genRuntimeCall("feraiseexcept", i32Ty, excepts); genRuntimeCall("feenableexcept", i32Ty, mask); } - builder.create(loc, result); + fir::ResultOp::create(builder, loc, result); } else { // Kind 2, 3, 4, 8, 16. Increment or decrement X cast to integer. - mlir::Value intX = builder.create(loc, intType, x); - mlir::Value add = builder.create(loc, intX, one); - mlir::Value sub = builder.create(loc, intX, one); - result = builder.create( - loc, resultType, - builder.create(loc, magnitudeUp, add, sub)); + mlir::Value intX = mlir::arith::BitcastOp::create(builder, loc, intType, x); + mlir::Value add = mlir::arith::AddIOp::create(builder, loc, intX, one); + mlir::Value sub = mlir::arith::SubIOp::create(builder, loc, intX, one); + result = mlir::arith::BitcastOp::create( + builder, loc, resultType, + mlir::arith::SelectOp::create(builder, loc, magnitudeUp, add, sub)); if constexpr (proc == NearestProc::Nearest || proc == NearestProc::NextAfter) { genRaiseExcept(_FORTRAN_RUNTIME_IEEE_OVERFLOW | @@ -7106,11 +7138,11 @@ mlir::Value IntrinsicLibrary::genNearest(mlir::Type resultType, _FORTRAN_RUNTIME_IEEE_INEXACT, genIsFPClass(i1Ty, result, subnormalTest)); } - builder.create(loc, result); + fir::ResultOp::create(builder, loc, result); } builder.setInsertionPointAfter(innerIfOp); - builder.create(loc, innerIfOp.getResult(0)); + fir::ResultOp::create(builder, loc, innerIfOp.getResult(0)); builder.setInsertionPointAfter(outerIfOp); return outerIfOp.getResult(0); } @@ -7192,10 +7224,18 @@ IntrinsicLibrary::genNull(mlir::Type, llvm::ArrayRef args) { mlir::Value boxStorage = builder.createTemporary(loc, boxType); mlir::Value box = fir::factory::createUnallocatedBox( builder, loc, boxType, mold->nonDeferredLenParams()); - builder.create(loc, box, boxStorage); + fir::StoreOp::create(builder, loc, box, boxStorage); return fir::MutableBoxValue(boxStorage, mold->nonDeferredLenParams(), {}); } +// CLOCK, CLOCK64, GLOBALTIMER +template +mlir::Value IntrinsicLibrary::genNVVMTime(mlir::Type resultType, + llvm::ArrayRef args) { + assert(args.size() == 0 && "expect no arguments"); + return OpTy::create(builder, loc, resultType).getResult(); +} + // PACK fir::ExtendedValue IntrinsicLibrary::genPack(mlir::Type resultType, @@ -7210,10 +7250,11 @@ IntrinsicLibrary::genPack(mlir::Type resultType, mlir::Value mask = builder.createBox(loc, args[1]); // Handle optional vector argument - mlir::Value vector = isStaticallyAbsent(args, 2) - ? builder.create( - loc, fir::BoxType::get(builder.getI1Type())) - : builder.createBox(loc, args[2]); + mlir::Value vector = + isStaticallyAbsent(args, 2) + ? fir::AbsentOp::create(builder, loc, + fir::BoxType::get(builder.getI1Type())) + : builder.createBox(loc, args[2]); // Create mutable fir.box to be passed to the runtime for the result. mlir::Type resultArrayType = builder.getVarLenSeqTy(resultType, 1); @@ -7273,7 +7314,7 @@ void IntrinsicLibrary::genPerror(llvm::ArrayRef args) { fir::ExtendedValue str = args[0]; const auto *box = str.getBoxOf(); mlir::Value addr = - builder.create(loc, box->getMemTy(), fir::getBase(*box)); + fir::BoxAddrOp::create(builder, loc, box->getMemTy(), fir::getBase(*box)); fir::runtime::genPerror(builder, loc, addr); } @@ -7282,7 +7323,7 @@ mlir::Value IntrinsicLibrary::genPopcnt(mlir::Type resultType, llvm::ArrayRef args) { assert(args.size() == 1); - mlir::Value count = builder.create(loc, args); + mlir::Value count = mlir::math::CtPopOp::create(builder, loc, args); return builder.createConvert(loc, resultType, count); } @@ -7295,7 +7336,7 @@ mlir::Value IntrinsicLibrary::genPoppar(mlir::Type resultType, mlir::Value count = genPopcnt(resultType, args); mlir::Value one = builder.createIntegerConstant(loc, resultType, 1); - return builder.create(loc, count, one); + return mlir::arith::AndIOp::create(builder, loc, count, one); } // PRESENT @@ -7303,8 +7344,8 @@ fir::ExtendedValue IntrinsicLibrary::genPresent(mlir::Type, llvm::ArrayRef args) { assert(args.size() == 1); - return builder.create(loc, builder.getI1Type(), - fir::getBase(args[0])); + return fir::IsPresentOp::create(builder, loc, builder.getI1Type(), + fir::getBase(args[0])); } // PRODUCT @@ -7369,7 +7410,7 @@ void IntrinsicLibrary::genRandomSeed(llvm::ArrayRef args) { auto getDesc = [&](int i) { return isStaticallyPresent(args[i]) ? fir::getBase(args[i]) - : builder.create(loc, boxNoneTy).getResult(); + : fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); }; mlir::Value size = getDesc(0); mlir::Value put = getDesc(1); @@ -7413,13 +7454,13 @@ IntrinsicLibrary::genReduce(mlir::Type resultType, bool absentDim = isStaticallyAbsent(args[2]); auto mask = isStaticallyAbsent(args[3]) - ? builder.create( - loc, fir::BoxType::get(builder.getI1Type())) + ? fir::AbsentOp::create( + builder, loc, fir::BoxType::get(builder.getI1Type())) : builder.createBox(loc, args[3]); mlir::Value identity = isStaticallyAbsent(args[4]) - ? builder.create(loc, fir::ReferenceType::get(eleTy)) + ? fir::AbsentOp::create(builder, loc, fir::ReferenceType::get(eleTy)) : fir::getBase(args[4]); mlir::Value ordered = isStaticallyAbsent(args[5]) @@ -7435,7 +7476,7 @@ IntrinsicLibrary::genReduce(mlir::Type resultType, ordered, result, argByRef); if (fir::isa_derived(eleTy)) return result; - return builder.create(loc, result); + return fir::LoadOp::create(builder, loc, result); } if (fir::isa_char(eleTy)) { auto charTy = mlir::dyn_cast_or_null(resultType); @@ -7485,7 +7526,7 @@ IntrinsicLibrary::genRename(std::optional resultType, auto statusAddr = builder.createTemporary(loc, *resultType); auto statusBox = builder.createBox(loc, statusAddr); fir::runtime::genRename(builder, loc, path1, path2, statusBox); - return builder.create(loc, statusAddr); + return fir::LoadOp::create(builder, loc, statusAddr); } else { // code-gen for the procedure form of RENAME mlir::Type boxNoneTy = fir::BoxType::get(builder.getNoneType()); @@ -7493,7 +7534,7 @@ IntrinsicLibrary::genRename(std::optional resultType, mlir::Value statusBox = isStaticallyPresent(status) ? fir::getBase(status) - : builder.create(loc, boxNoneTy).getResult(); + : fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); fir::runtime::genRename(builder, loc, path1, path2, statusBox); return {}; } @@ -7538,16 +7579,18 @@ IntrinsicLibrary::genReshape(mlir::Type resultType, TODO(loc, "intrinsic: reshape requires computing rank of result"); // Handle optional pad argument - mlir::Value pad = isStaticallyAbsent(args[2]) - ? builder.create( - loc, fir::BoxType::get(builder.getI1Type())) - : builder.createBox(loc, args[2]); + mlir::Value pad = + isStaticallyAbsent(args[2]) + ? fir::AbsentOp::create(builder, loc, + fir::BoxType::get(builder.getI1Type())) + : builder.createBox(loc, args[2]); // Handle optional order argument - mlir::Value order = isStaticallyAbsent(args[3]) - ? builder.create( - loc, fir::BoxType::get(builder.getI1Type())) - : builder.createBox(loc, args[3]); + mlir::Value order = + isStaticallyAbsent(args[3]) + ? fir::AbsentOp::create(builder, loc, + fir::BoxType::get(builder.getI1Type())) + : builder.createBox(loc, args[3]); // Create mutable fir.box to be passed to the runtime for the result. mlir::Type type = builder.getVarLenSeqTy(resultType, resultRank); @@ -7618,26 +7661,27 @@ mlir::Value IntrinsicLibrary::genScale(mlir::Type resultType, // If X is finite and result is infinite, signal IEEE_OVERFLOW // If X is finite and scale(result, -I) != X, signal IEEE_UNDERFLOW fir::IfOp outerIfOp = - builder.create(loc, genIsFPClass(i1Ty, args[0], finiteTest), - /*withElseRegion=*/false); + fir::IfOp::create(builder, loc, genIsFPClass(i1Ty, args[0], finiteTest), + /*withElseRegion=*/false); builder.setInsertionPointToStart(&outerIfOp.getThenRegion().front()); fir::IfOp innerIfOp = - builder.create(loc, genIsFPClass(i1Ty, result, infiniteTest), - /*withElseRegion=*/true); + fir::IfOp::create(builder, loc, genIsFPClass(i1Ty, result, infiniteTest), + /*withElseRegion=*/true); builder.setInsertionPointToStart(&innerIfOp.getThenRegion().front()); genRaiseExcept(_FORTRAN_RUNTIME_IEEE_OVERFLOW | _FORTRAN_RUNTIME_IEEE_INEXACT); builder.setInsertionPointToStart(&innerIfOp.getElseRegion().front()); - mlir::Value minusI = builder.create( - loc, args[1], builder.createAllOnesInteger(loc, args[1].getType())); + mlir::Value minusI = mlir::arith::MulIOp::create( + builder, loc, args[1], + builder.createAllOnesInteger(loc, args[1].getType())); mlir::Value reverseResult = builder.createConvert( loc, resultType, fir::runtime::genScale( builder, loc, builder.createConvert(loc, f32Ty, result), minusI)); genRaiseExcept( _FORTRAN_RUNTIME_IEEE_UNDERFLOW | _FORTRAN_RUNTIME_IEEE_INEXACT, - builder.create(loc, mlir::arith::CmpFPredicate::ONE, - args[0], reverseResult)); + mlir::arith::CmpFOp::create(builder, loc, mlir::arith::CmpFPredicate::ONE, + args[0], reverseResult)); builder.setInsertionPointAfter(outerIfOp); return result; } @@ -7689,13 +7733,14 @@ IntrinsicLibrary::genScan(mlir::Type resultType, builder.getContext(), builder.getKindMap().defaultLogicalKind()); mlir::Value temp = builder.createTemporary(loc, logTy); mlir::Value castb = builder.createConvert(loc, logTy, b); - builder.create(loc, castb, temp); + fir::StoreOp::create(builder, loc, castb, temp); return builder.createBox(loc, temp); }; - mlir::Value back = fir::isUnboxedValue(args[2]) - ? makeRefThenEmbox(*args[2].getUnboxed()) - : builder.create( - loc, fir::BoxType::get(builder.getI1Type())); + mlir::Value back = + fir::isUnboxedValue(args[2]) + ? makeRefThenEmbox(*args[2].getUnboxed()) + : fir::AbsentOp::create(builder, loc, + fir::BoxType::get(builder.getI1Type())); // Handle required string argument mlir::Value string = builder.createBox(loc, args[0]); @@ -7736,7 +7781,7 @@ IntrinsicLibrary::genSecond(std::optional resultType, genCpuTime(subroutineArgs); if (resultType) - return builder.create(loc, fir::getBase(result)); + return fir::LoadOp::create(builder, loc, fir::getBase(result)); return {}; } @@ -7783,22 +7828,22 @@ IntrinsicLibrary::genSelectedRealKind(mlir::Type resultType, // Handle optional precision(P) argument mlir::Value precision = isStaticallyAbsent(args[0]) - ? builder.create( - loc, fir::ReferenceType::get(builder.getI1Type())) + ? fir::AbsentOp::create(builder, loc, + fir::ReferenceType::get(builder.getI1Type())) : fir::getBase(args[0]); // Handle optional range(R) argument mlir::Value range = isStaticallyAbsent(args[1]) - ? builder.create( - loc, fir::ReferenceType::get(builder.getI1Type())) + ? fir::AbsentOp::create(builder, loc, + fir::ReferenceType::get(builder.getI1Type())) : fir::getBase(args[1]); // Handle optional radix(RADIX) argument mlir::Value radix = isStaticallyAbsent(args[2]) - ? builder.create( - loc, fir::ReferenceType::get(builder.getI1Type())) + ? fir::AbsentOp::create(builder, loc, + fir::ReferenceType::get(builder.getI1Type())) : fir::getBase(args[2]); return builder.createConvert( @@ -7836,9 +7881,9 @@ createBoxForRuntimeBoundInquiry(mlir::Location loc, fir::FirOpBuilder &builder, // shape information. mlir::Value localShape = builder.createShape(loc, array); mlir::Value oldBox = boxValue.getAddr(); - return builder.create(loc, oldBox.getType(), oldBox, - localShape, - /*slice=*/mlir::Value{}); + return fir::ReboxOp::create(builder, loc, oldBox.getType(), oldBox, + localShape, + /*slice=*/mlir::Value{}); }, [&](const auto &) -> mlir::Value { // This is a pointer/allocatable, or an entity not yet tracked with a @@ -7884,7 +7929,7 @@ genBoundInquiry(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value resultBase = builder.createConvert(loc, baseType, resultStorage); mlir::Value rankValue = - builder.create(loc, builder.getIndexType(), arrayBox); + fir::BoxRankOp::create(builder, loc, builder.getIndexType(), arrayBox); return fir::ArrayBoxValue{resultBase, {rankValue}}; } // Result extent is a compile time constant in the other cases. @@ -7914,9 +7959,9 @@ IntrinsicLibrary::genShape(mlir::Type resultType, mlir::Value extent = fir::factory::readExtent(builder, loc, array, dim); extent = builder.createConvert(loc, extentType, extent); auto index = builder.createIntegerConstant(loc, indexType, dim); - auto shapeAddr = builder.create(loc, shapeAddrType, - shapeArray, index); - builder.create(loc, extent, shapeAddr); + auto shapeAddr = fir::CoordinateOp::create(builder, loc, shapeAddrType, + shapeArray, index); + fir::StoreOp::create(builder, loc, extent, shapeAddr); } mlir::Value shapeArrayExtent = builder.createIntegerConstant(loc, indexType, rank); @@ -7942,18 +7987,18 @@ mlir::Value IntrinsicLibrary::genShift(mlir::Type resultType, mlir::Value zero = builder.createIntegerConstant(loc, signlessType, 0); mlir::Value shift = builder.createConvert(loc, signlessType, args[1]); - mlir::Value tooSmall = builder.create( - loc, mlir::arith::CmpIPredicate::slt, shift, zero); - mlir::Value tooLarge = builder.create( - loc, mlir::arith::CmpIPredicate::sge, shift, bitSize); + mlir::Value tooSmall = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::slt, shift, zero); + mlir::Value tooLarge = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::sge, shift, bitSize); mlir::Value outOfBounds = - builder.create(loc, tooSmall, tooLarge); + mlir::arith::OrIOp::create(builder, loc, tooSmall, tooLarge); mlir::Value word = args[0]; if (word.getType().isUnsignedInteger()) word = builder.createConvert(loc, signlessType, word); - mlir::Value shifted = builder.create(loc, word, shift); + mlir::Value shifted = Shift::create(builder, loc, word, shift); mlir::Value result = - builder.create(loc, outOfBounds, zero, shifted); + mlir::arith::SelectOp::create(builder, loc, outOfBounds, zero, shifted); if (resultType.isUnsignedInteger()) return builder.createConvert(loc, resultType, result); return result; @@ -7968,8 +8013,8 @@ mlir::Value IntrinsicLibrary::genShiftA(mlir::Type resultType, mlir::IntegerType::SignednessSemantics::Signless); mlir::Value bitSize = builder.createIntegerConstant(loc, signlessType, bits); mlir::Value shift = builder.createConvert(loc, signlessType, args[1]); - mlir::Value shiftGeBitSize = builder.create( - loc, mlir::arith::CmpIPredicate::uge, shift, bitSize); + mlir::Value shiftGeBitSize = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::uge, shift, bitSize); // Lowering of mlir::arith::ShRSIOp is using `ashr`. `ashr` is undefined when // the shift amount is equal to the element size. @@ -7981,13 +8026,13 @@ mlir::Value IntrinsicLibrary::genShiftA(mlir::Type resultType, mlir::Value word = args[0]; if (word.getType().isUnsignedInteger()) word = builder.createConvert(loc, signlessType, word); - mlir::Value valueIsNeg = builder.create( - loc, mlir::arith::CmpIPredicate::slt, word, zero); + mlir::Value valueIsNeg = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::slt, word, zero); mlir::Value specialRes = - builder.create(loc, valueIsNeg, minusOne, zero); - mlir::Value shifted = builder.create(loc, word, shift); - mlir::Value result = builder.create( - loc, shiftGeBitSize, specialRes, shifted); + mlir::arith::SelectOp::create(builder, loc, valueIsNeg, minusOne, zero); + mlir::Value shifted = mlir::arith::ShRSIOp::create(builder, loc, word, shift); + mlir::Value result = mlir::arith::SelectOp::create( + builder, loc, shiftGeBitSize, specialRes, shifted); if (resultType.isUnsignedInteger()) return builder.createConvert(loc, resultType, result); return result; @@ -8012,10 +8057,10 @@ mlir::Value IntrinsicLibrary::genSign(mlir::Type resultType, if (mlir::isa(resultType)) { mlir::Value abs = genAbs(resultType, {args[0]}); mlir::Value zero = builder.createIntegerConstant(loc, resultType, 0); - auto neg = builder.create(loc, zero, abs); - auto cmp = builder.create( - loc, mlir::arith::CmpIPredicate::slt, args[1], zero); - return builder.create(loc, cmp, neg, abs); + auto neg = mlir::arith::SubIOp::create(builder, loc, zero, abs); + auto cmp = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::slt, args[1], zero); + return mlir::arith::SelectOp::create(builder, loc, cmp, neg, abs); } return genRuntimeCall("sign", resultType, args); } @@ -8031,6 +8076,21 @@ mlir::Value IntrinsicLibrary::genSind(mlir::Type resultType, mlir::Value dfactor = builder.createRealConstant( loc, mlir::Float64Type::get(context), pi / llvm::APFloat(180.0)); mlir::Value factor = builder.createConvert(loc, args[0].getType(), dfactor); + mlir::Value arg = mlir::arith::MulFOp::create(builder, loc, args[0], factor); + return getRuntimeCallGenerator("sin", ftype)(builder, loc, {arg}); +} + +// SINPI +mlir::Value IntrinsicLibrary::genSinpi(mlir::Type resultType, + llvm::ArrayRef args) { + assert(args.size() == 1); + mlir::MLIRContext *context = builder.getContext(); + mlir::FunctionType ftype = + mlir::FunctionType::get(context, {resultType}, {args[0].getType()}); + llvm::APFloat pi = llvm::APFloat(llvm::numbers::pi); + mlir::Value dfactor = + builder.createRealConstant(loc, mlir::Float64Type::get(context), pi); + mlir::Value factor = builder.createConvert(loc, args[0].getType(), dfactor); mlir::Value arg = builder.create(loc, args[0], factor); return getRuntimeCallGenerator("sin", ftype)(builder, loc, {arg}); } @@ -8075,14 +8135,14 @@ IntrinsicLibrary::genSize(mlir::Type resultType, .genThen([&]() { mlir::Value size = builder.createConvert( loc, resultType, fir::runtime::genSize(builder, loc, array)); - builder.create(loc, size); + fir::ResultOp::create(builder, loc, size); }) .genElse([&]() { - mlir::Value dimValue = builder.create(loc, dim); + mlir::Value dimValue = fir::LoadOp::create(builder, loc, dim); mlir::Value size = builder.createConvert( loc, resultType, fir::runtime::genSizeDim(builder, loc, array, dimValue)); - builder.create(loc, size); + fir::ResultOp::create(builder, loc, size); }) .getResults()[0]; } @@ -8093,12 +8153,13 @@ IntrinsicLibrary::genSizeOf(mlir::Type resultType, llvm::ArrayRef args) { assert(args.size() == 1); mlir::Value box = fir::getBase(args[0]); - mlir::Value eleSize = builder.create(loc, resultType, box); + mlir::Value eleSize = + fir::BoxEleSizeOp::create(builder, loc, resultType, box); if (!fir::isArray(args[0])) return eleSize; mlir::Value arraySize = builder.createConvert( loc, resultType, fir::runtime::genSize(builder, loc, box)); - return builder.create(loc, eleSize, arraySize); + return mlir::arith::MulIOp::create(builder, loc, eleSize, arraySize); } // TAND @@ -8112,7 +8173,7 @@ mlir::Value IntrinsicLibrary::genTand(mlir::Type resultType, mlir::Value dfactor = builder.createRealConstant( loc, mlir::Float64Type::get(context), pi / llvm::APFloat(180.0)); mlir::Value factor = builder.createConvert(loc, args[0].getType(), dfactor); - mlir::Value arg = builder.create(loc, args[0], factor); + mlir::Value arg = mlir::arith::MulFOp::create(builder, loc, args[0], factor); return getRuntimeCallGenerator("tan", ftype)(builder, loc, {arg}); } @@ -8122,81 +8183,83 @@ mlir::Value IntrinsicLibrary::genThisGrid(mlir::Type resultType, assert(args.size() == 0); auto recTy = mlir::cast(resultType); assert(recTy && "RecordType expepected"); - mlir::Value res = builder.create(loc, resultType); + mlir::Value res = fir::AllocaOp::create(builder, loc, resultType); mlir::Type i32Ty = builder.getI32Type(); - mlir::Value threadIdX = builder.create(loc, i32Ty); - mlir::Value threadIdY = builder.create(loc, i32Ty); - mlir::Value threadIdZ = builder.create(loc, i32Ty); + mlir::Value threadIdX = mlir::NVVM::ThreadIdXOp::create(builder, loc, i32Ty); + mlir::Value threadIdY = mlir::NVVM::ThreadIdYOp::create(builder, loc, i32Ty); + mlir::Value threadIdZ = mlir::NVVM::ThreadIdZOp::create(builder, loc, i32Ty); - mlir::Value blockIdX = builder.create(loc, i32Ty); - mlir::Value blockIdY = builder.create(loc, i32Ty); - mlir::Value blockIdZ = builder.create(loc, i32Ty); + mlir::Value blockIdX = mlir::NVVM::BlockIdXOp::create(builder, loc, i32Ty); + mlir::Value blockIdY = mlir::NVVM::BlockIdYOp::create(builder, loc, i32Ty); + mlir::Value blockIdZ = mlir::NVVM::BlockIdZOp::create(builder, loc, i32Ty); - mlir::Value blockDimX = builder.create(loc, i32Ty); - mlir::Value blockDimY = builder.create(loc, i32Ty); - mlir::Value blockDimZ = builder.create(loc, i32Ty); - mlir::Value gridDimX = builder.create(loc, i32Ty); - mlir::Value gridDimY = builder.create(loc, i32Ty); - mlir::Value gridDimZ = builder.create(loc, i32Ty); + mlir::Value blockDimX = mlir::NVVM::BlockDimXOp::create(builder, loc, i32Ty); + mlir::Value blockDimY = mlir::NVVM::BlockDimYOp::create(builder, loc, i32Ty); + mlir::Value blockDimZ = mlir::NVVM::BlockDimZOp::create(builder, loc, i32Ty); + mlir::Value gridDimX = mlir::NVVM::GridDimXOp::create(builder, loc, i32Ty); + mlir::Value gridDimY = mlir::NVVM::GridDimYOp::create(builder, loc, i32Ty); + mlir::Value gridDimZ = mlir::NVVM::GridDimZOp::create(builder, loc, i32Ty); // this_grid.size = ((blockDim.z * gridDim.z) * (blockDim.y * gridDim.y)) * // (blockDim.x * gridDim.x); mlir::Value resZ = - builder.create(loc, blockDimZ, gridDimZ); + mlir::arith::MulIOp::create(builder, loc, blockDimZ, gridDimZ); mlir::Value resY = - builder.create(loc, blockDimY, gridDimY); + mlir::arith::MulIOp::create(builder, loc, blockDimY, gridDimY); mlir::Value resX = - builder.create(loc, blockDimX, gridDimX); - mlir::Value resZY = builder.create(loc, resZ, resY); - mlir::Value size = builder.create(loc, resZY, resX); + mlir::arith::MulIOp::create(builder, loc, blockDimX, gridDimX); + mlir::Value resZY = mlir::arith::MulIOp::create(builder, loc, resZ, resY); + mlir::Value size = mlir::arith::MulIOp::create(builder, loc, resZY, resX); // tmp = ((blockIdx.z * gridDim.y * gridDim.x) + (blockIdx.y * gridDim.x)) + // blockIdx.x; // this_group.rank = tmp * ((blockDim.x * blockDim.y) * blockDim.z) + // ((threadIdx.z * blockDim.y) * blockDim.x) + // (threadIdx.y * blockDim.x) + threadIdx.x + 1; - mlir::Value r1 = builder.create(loc, blockIdZ, gridDimY); - mlir::Value r2 = builder.create(loc, r1, gridDimX); - mlir::Value r3 = builder.create(loc, blockIdY, gridDimX); - mlir::Value r2r3 = builder.create(loc, r2, r3); - mlir::Value tmp = builder.create(loc, r2r3, blockIdX); + mlir::Value r1 = + mlir::arith::MulIOp::create(builder, loc, blockIdZ, gridDimY); + mlir::Value r2 = mlir::arith::MulIOp::create(builder, loc, r1, gridDimX); + mlir::Value r3 = + mlir::arith::MulIOp::create(builder, loc, blockIdY, gridDimX); + mlir::Value r2r3 = mlir::arith::AddIOp::create(builder, loc, r2, r3); + mlir::Value tmp = mlir::arith::AddIOp::create(builder, loc, r2r3, blockIdX); mlir::Value bXbY = - builder.create(loc, blockDimX, blockDimY); + mlir::arith::MulIOp::create(builder, loc, blockDimX, blockDimY); mlir::Value bXbYbZ = - builder.create(loc, bXbY, blockDimZ); + mlir::arith::MulIOp::create(builder, loc, bXbY, blockDimZ); mlir::Value tZbY = - builder.create(loc, threadIdZ, blockDimY); + mlir::arith::MulIOp::create(builder, loc, threadIdZ, blockDimY); mlir::Value tZbYbX = - builder.create(loc, tZbY, blockDimX); + mlir::arith::MulIOp::create(builder, loc, tZbY, blockDimX); mlir::Value tYbX = - builder.create(loc, threadIdY, blockDimX); - mlir::Value rank = builder.create(loc, tmp, bXbYbZ); - rank = builder.create(loc, rank, tZbYbX); - rank = builder.create(loc, rank, tYbX); - rank = builder.create(loc, rank, threadIdX); + mlir::arith::MulIOp::create(builder, loc, threadIdY, blockDimX); + mlir::Value rank = mlir::arith::MulIOp::create(builder, loc, tmp, bXbYbZ); + rank = mlir::arith::AddIOp::create(builder, loc, rank, tZbYbX); + rank = mlir::arith::AddIOp::create(builder, loc, rank, tYbX); + rank = mlir::arith::AddIOp::create(builder, loc, rank, threadIdX); mlir::Value one = builder.createIntegerConstant(loc, i32Ty, 1); - rank = builder.create(loc, rank, one); + rank = mlir::arith::AddIOp::create(builder, loc, rank, one); auto sizeFieldName = recTy.getTypeList()[1].first; mlir::Type sizeFieldTy = recTy.getTypeList()[1].second; mlir::Type fieldIndexType = fir::FieldType::get(resultType.getContext()); - mlir::Value sizeFieldIndex = builder.create( - loc, fieldIndexType, sizeFieldName, recTy, + mlir::Value sizeFieldIndex = fir::FieldIndexOp::create( + builder, loc, fieldIndexType, sizeFieldName, recTy, /*typeParams=*/mlir::ValueRange{}); - mlir::Value sizeCoord = builder.create( - loc, builder.getRefType(sizeFieldTy), res, sizeFieldIndex); - builder.create(loc, size, sizeCoord); + mlir::Value sizeCoord = fir::CoordinateOp::create( + builder, loc, builder.getRefType(sizeFieldTy), res, sizeFieldIndex); + fir::StoreOp::create(builder, loc, size, sizeCoord); auto rankFieldName = recTy.getTypeList()[2].first; mlir::Type rankFieldTy = recTy.getTypeList()[2].second; - mlir::Value rankFieldIndex = builder.create( - loc, fieldIndexType, rankFieldName, recTy, + mlir::Value rankFieldIndex = fir::FieldIndexOp::create( + builder, loc, fieldIndexType, rankFieldName, recTy, /*typeParams=*/mlir::ValueRange{}); - mlir::Value rankCoord = builder.create( - loc, builder.getRefType(rankFieldTy), res, rankFieldIndex); - builder.create(loc, rank, rankCoord); + mlir::Value rankCoord = fir::CoordinateOp::create( + builder, loc, builder.getRefType(rankFieldTy), res, rankFieldIndex); + fir::StoreOp::create(builder, loc, rank, rankCoord); return res; } @@ -8207,50 +8270,50 @@ IntrinsicLibrary::genThisThreadBlock(mlir::Type resultType, assert(args.size() == 0); auto recTy = mlir::cast(resultType); assert(recTy && "RecordType expepected"); - mlir::Value res = builder.create(loc, resultType); + mlir::Value res = fir::AllocaOp::create(builder, loc, resultType); mlir::Type i32Ty = builder.getI32Type(); // this_thread_block%size = blockDim.z * blockDim.y * blockDim.x; - mlir::Value blockDimX = builder.create(loc, i32Ty); - mlir::Value blockDimY = builder.create(loc, i32Ty); - mlir::Value blockDimZ = builder.create(loc, i32Ty); + mlir::Value blockDimX = mlir::NVVM::BlockDimXOp::create(builder, loc, i32Ty); + mlir::Value blockDimY = mlir::NVVM::BlockDimYOp::create(builder, loc, i32Ty); + mlir::Value blockDimZ = mlir::NVVM::BlockDimZOp::create(builder, loc, i32Ty); mlir::Value size = - builder.create(loc, blockDimZ, blockDimY); - size = builder.create(loc, size, blockDimX); + mlir::arith::MulIOp::create(builder, loc, blockDimZ, blockDimY); + size = mlir::arith::MulIOp::create(builder, loc, size, blockDimX); // this_thread_block%rank = ((threadIdx.z * blockDim.y) * blockDim.x) + // (threadIdx.y * blockDim.x) + threadIdx.x + 1; - mlir::Value threadIdX = builder.create(loc, i32Ty); - mlir::Value threadIdY = builder.create(loc, i32Ty); - mlir::Value threadIdZ = builder.create(loc, i32Ty); + mlir::Value threadIdX = mlir::NVVM::ThreadIdXOp::create(builder, loc, i32Ty); + mlir::Value threadIdY = mlir::NVVM::ThreadIdYOp::create(builder, loc, i32Ty); + mlir::Value threadIdZ = mlir::NVVM::ThreadIdZOp::create(builder, loc, i32Ty); mlir::Value r1 = - builder.create(loc, threadIdZ, blockDimY); - mlir::Value r2 = builder.create(loc, r1, blockDimX); + mlir::arith::MulIOp::create(builder, loc, threadIdZ, blockDimY); + mlir::Value r2 = mlir::arith::MulIOp::create(builder, loc, r1, blockDimX); mlir::Value r3 = - builder.create(loc, threadIdY, blockDimX); - mlir::Value r2r3 = builder.create(loc, r2, r3); - mlir::Value rank = builder.create(loc, r2r3, threadIdX); + mlir::arith::MulIOp::create(builder, loc, threadIdY, blockDimX); + mlir::Value r2r3 = mlir::arith::AddIOp::create(builder, loc, r2, r3); + mlir::Value rank = mlir::arith::AddIOp::create(builder, loc, r2r3, threadIdX); mlir::Value one = builder.createIntegerConstant(loc, i32Ty, 1); - rank = builder.create(loc, rank, one); + rank = mlir::arith::AddIOp::create(builder, loc, rank, one); auto sizeFieldName = recTy.getTypeList()[1].first; mlir::Type sizeFieldTy = recTy.getTypeList()[1].second; mlir::Type fieldIndexType = fir::FieldType::get(resultType.getContext()); - mlir::Value sizeFieldIndex = builder.create( - loc, fieldIndexType, sizeFieldName, recTy, + mlir::Value sizeFieldIndex = fir::FieldIndexOp::create( + builder, loc, fieldIndexType, sizeFieldName, recTy, /*typeParams=*/mlir::ValueRange{}); - mlir::Value sizeCoord = builder.create( - loc, builder.getRefType(sizeFieldTy), res, sizeFieldIndex); - builder.create(loc, size, sizeCoord); + mlir::Value sizeCoord = fir::CoordinateOp::create( + builder, loc, builder.getRefType(sizeFieldTy), res, sizeFieldIndex); + fir::StoreOp::create(builder, loc, size, sizeCoord); auto rankFieldName = recTy.getTypeList()[2].first; mlir::Type rankFieldTy = recTy.getTypeList()[2].second; - mlir::Value rankFieldIndex = builder.create( - loc, fieldIndexType, rankFieldName, recTy, + mlir::Value rankFieldIndex = fir::FieldIndexOp::create( + builder, loc, fieldIndexType, rankFieldName, recTy, /*typeParams=*/mlir::ValueRange{}); - mlir::Value rankCoord = builder.create( - loc, builder.getRefType(rankFieldTy), res, rankFieldIndex); - builder.create(loc, rank, rankCoord); + mlir::Value rankCoord = fir::CoordinateOp::create( + builder, loc, builder.getRefType(rankFieldTy), res, rankFieldIndex); + fir::StoreOp::create(builder, loc, rank, rankCoord); return res; } @@ -8260,7 +8323,7 @@ mlir::Value IntrinsicLibrary::genThisWarp(mlir::Type resultType, assert(args.size() == 0); auto recTy = mlir::cast(resultType); assert(recTy && "RecordType expepected"); - mlir::Value res = builder.create(loc, resultType); + mlir::Value res = fir::AllocaOp::create(builder, loc, resultType); mlir::Type i32Ty = builder.getI32Type(); // coalesced_group%size = 32 @@ -8268,28 +8331,28 @@ mlir::Value IntrinsicLibrary::genThisWarp(mlir::Type resultType, auto sizeFieldName = recTy.getTypeList()[1].first; mlir::Type sizeFieldTy = recTy.getTypeList()[1].second; mlir::Type fieldIndexType = fir::FieldType::get(resultType.getContext()); - mlir::Value sizeFieldIndex = builder.create( - loc, fieldIndexType, sizeFieldName, recTy, + mlir::Value sizeFieldIndex = fir::FieldIndexOp::create( + builder, loc, fieldIndexType, sizeFieldName, recTy, /*typeParams=*/mlir::ValueRange{}); - mlir::Value sizeCoord = builder.create( - loc, builder.getRefType(sizeFieldTy), res, sizeFieldIndex); - builder.create(loc, size, sizeCoord); + mlir::Value sizeCoord = fir::CoordinateOp::create( + builder, loc, builder.getRefType(sizeFieldTy), res, sizeFieldIndex); + fir::StoreOp::create(builder, loc, size, sizeCoord); // coalesced_group%rank = threadIdx.x & 31 + 1 - mlir::Value threadIdX = builder.create(loc, i32Ty); + mlir::Value threadIdX = mlir::NVVM::ThreadIdXOp::create(builder, loc, i32Ty); mlir::Value mask = builder.createIntegerConstant(loc, i32Ty, 31); mlir::Value one = builder.createIntegerConstant(loc, i32Ty, 1); mlir::Value masked = - builder.create(loc, threadIdX, mask); - mlir::Value rank = builder.create(loc, masked, one); + mlir::arith::AndIOp::create(builder, loc, threadIdX, mask); + mlir::Value rank = mlir::arith::AddIOp::create(builder, loc, masked, one); auto rankFieldName = recTy.getTypeList()[2].first; mlir::Type rankFieldTy = recTy.getTypeList()[2].second; - mlir::Value rankFieldIndex = builder.create( - loc, fieldIndexType, rankFieldName, recTy, + mlir::Value rankFieldIndex = fir::FieldIndexOp::create( + builder, loc, fieldIndexType, rankFieldName, recTy, /*typeParams=*/mlir::ValueRange{}); - mlir::Value rankCoord = builder.create( - loc, builder.getRefType(rankFieldTy), res, rankFieldIndex); - builder.create(loc, rank, rankCoord); + mlir::Value rankCoord = fir::CoordinateOp::create( + builder, loc, builder.getRefType(rankFieldTy), res, rankFieldIndex); + fir::StoreOp::create(builder, loc, rank, rankCoord); return res; } @@ -8299,7 +8362,7 @@ mlir::Value IntrinsicLibrary::genTrailz(mlir::Type resultType, assert(args.size() == 1); mlir::Value result = - builder.create(loc, args); + mlir::math::CountTrailingZerosOp::create(builder, loc, args); return builder.createConvert(loc, resultType, result); } @@ -8327,10 +8390,10 @@ static mlir::Value computeLBOUND(fir::FirOpBuilder &builder, mlir::Location loc, zero = builder.createConvert(loc, extent.getType(), zero); // Note: for assumed size, the extent is -1, and the lower bound should // be returned. It is important to test extent == 0 and not extent > 0. - auto dimIsEmpty = builder.create( - loc, mlir::arith::CmpIPredicate::eq, extent, zero); + auto dimIsEmpty = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, extent, zero); one = builder.createConvert(loc, lb.getType(), one); - return builder.create(loc, dimIsEmpty, one, lb); + return mlir::arith::SelectOp::create(builder, loc, dimIsEmpty, one, lb); } // LBOUND @@ -8366,8 +8429,8 @@ IntrinsicLibrary::genLbound(mlir::Type resultType, lb = builder.createConvert(loc, lbType, lb); auto index = builder.createIntegerConstant(loc, indexType, dim); auto lbAddr = - builder.create(loc, lbAddrType, lbArray, index); - builder.create(loc, lb, lbAddr); + fir::CoordinateOp::create(builder, loc, lbAddrType, lbArray, index); + fir::StoreOp::create(builder, loc, lb, lbAddr); } mlir::Value lbArrayExtent = builder.createIntegerConstant(loc, indexType, rank); @@ -8406,8 +8469,8 @@ IntrinsicLibrary::genUbound(mlir::Type resultType, mlir::Value lbound = fir::getBase(genLbound(resultType, args)); mlir::Value one = builder.createIntegerConstant(loc, resultType, 1); - mlir::Value ubound = builder.create(loc, lbound, one); - return builder.create(loc, ubound, extent); + mlir::Value ubound = mlir::arith::SubIOp::create(builder, loc, lbound, one); + return mlir::arith::AddIOp::create(builder, loc, ubound, extent); } // Handle calls to UBOUND without the DIM argument, which return an array int kindPos = args.size() == 2 ? 1 : 2; @@ -8501,9 +8564,9 @@ IntrinsicLibrary::genStorageSize(mlir::Type resultType, box = builder.createBox(loc, args[0], /*isPolymorphic=*/args[0].isPolymorphic()); - mlir::Value eleSize = builder.create(loc, kindTy, box); + mlir::Value eleSize = fir::BoxEleSizeOp::create(builder, loc, kindTy, box); mlir::Value c8 = builder.createIntegerConstant(loc, kindTy, 8); - return builder.create(loc, eleSize, c8); + return mlir::arith::MulIOp::create(builder, loc, eleSize, c8); } // SUM @@ -8516,7 +8579,7 @@ IntrinsicLibrary::genSum(mlir::Type resultType, // SYNCTHREADS void IntrinsicLibrary::genSyncThreads(llvm::ArrayRef args) { - builder.create(loc); + mlir::NVVM::Barrier0Op::create(builder, loc); } // SYNCTHREADS_AND @@ -8528,7 +8591,7 @@ IntrinsicLibrary::genSyncThreadsAnd(mlir::Type resultType, mlir::FunctionType ftype = mlir::FunctionType::get(context, {resultType}, {args[0].getType()}); auto funcOp = builder.createFunction(loc, funcName, ftype); - return builder.create(loc, funcOp, args).getResult(0); + return fir::CallOp::create(builder, loc, funcOp, args).getResult(0); } // SYNCTHREADS_COUNT @@ -8540,7 +8603,7 @@ IntrinsicLibrary::genSyncThreadsCount(mlir::Type resultType, mlir::FunctionType ftype = mlir::FunctionType::get(context, {resultType}, {args[0].getType()}); auto funcOp = builder.createFunction(loc, funcName, ftype); - return builder.create(loc, funcOp, args).getResult(0); + return fir::CallOp::create(builder, loc, funcOp, args).getResult(0); } // SYNCTHREADS_OR @@ -8552,7 +8615,7 @@ IntrinsicLibrary::genSyncThreadsOr(mlir::Type resultType, mlir::FunctionType ftype = mlir::FunctionType::get(context, {resultType}, {args[0].getType()}); auto funcOp = builder.createFunction(loc, funcName, ftype); - return builder.create(loc, funcOp, args).getResult(0); + return fir::CallOp::create(builder, loc, funcOp, args).getResult(0); } // SYNCWARP @@ -8564,7 +8627,7 @@ void IntrinsicLibrary::genSyncWarp(llvm::ArrayRef args) { mlir::FunctionType::get(builder.getContext(), {mask.getType()}, {}); auto funcOp = builder.createFunction(loc, funcName, funcType); llvm::SmallVector argsList{mask}; - builder.create(loc, funcOp, argsList); + fir::CallOp::create(builder, loc, funcOp, argsList); } // SYSTEM @@ -8590,25 +8653,26 @@ IntrinsicLibrary::genSystem(std::optional resultType, mlir::Value exitstatBox = isStaticallyPresent(exitstat) ? fir::getBase(exitstat) - : builder.create(loc, boxNoneTy).getResult(); + : fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); // Create a dummmy cmdstat to prevent EXECUTE_COMMAND_LINE terminate itself // when cmdstat is assigned with a non-zero value but not present mlir::Value tempValue = builder.createIntegerConstant(loc, builder.getI16Type(), 0); mlir::Value temp = builder.createTemporary(loc, builder.getI16Type()); - builder.create(loc, tempValue, temp); + fir::StoreOp::create(builder, loc, tempValue, temp); mlir::Value cmdstatBox = builder.createBox(loc, temp); mlir::Value cmdmsgBox = - builder.create(loc, boxNoneTy).getResult(); + fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); fir::runtime::genExecuteCommandLine(builder, loc, command, waitBool, exitstatBox, cmdstatBox, cmdmsgBox); if (resultType) { - mlir::Value exitstatAddr = builder.create(loc, exitstatBox); - return builder.create(loc, fir::getBase(exitstatAddr)); + mlir::Value exitstatAddr = + fir::BoxAddrOp::create(builder, loc, exitstatBox); + return fir::LoadOp::create(builder, loc, fir::getBase(exitstatAddr)); } return {}; } @@ -8704,7 +8768,7 @@ void IntrinsicLibrary::genThreadFence(llvm::ArrayRef args) { mlir::FunctionType::get(builder.getContext(), {}, {}); auto funcOp = builder.createFunction(loc, funcName, funcType); llvm::SmallVector noArgs; - builder.create(loc, funcOp, noArgs); + fir::CallOp::create(builder, loc, funcOp, noArgs); } // THREADFENCE_BLOCK @@ -8715,7 +8779,7 @@ void IntrinsicLibrary::genThreadFenceBlock( mlir::FunctionType::get(builder.getContext(), {}, {}); auto funcOp = builder.createFunction(loc, funcName, funcType); llvm::SmallVector noArgs; - builder.create(loc, funcOp, noArgs); + fir::CallOp::create(builder, loc, funcOp, noArgs); } // THREADFENCE_SYSTEM @@ -8726,7 +8790,7 @@ void IntrinsicLibrary::genThreadFenceSystem( mlir::FunctionType::get(builder.getContext(), {}, {}); auto funcOp = builder.createFunction(loc, funcName, funcType); llvm::SmallVector noArgs; - builder.create(loc, funcOp, noArgs); + fir::CallOp::create(builder, loc, funcOp, noArgs); } // TIME @@ -8778,29 +8842,30 @@ static mlir::Value createExtremumCompare(mlir::Location loc, // Return the number if one of the inputs is NaN and the other is // a number. auto leftIsResult = - builder.create(loc, orderedCmp, left, right); - auto rightIsNan = builder.create( - loc, mlir::arith::CmpFPredicate::UNE, right, right); + mlir::arith::CmpFOp::create(builder, loc, orderedCmp, left, right); + auto rightIsNan = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::UNE, right, right); result = - builder.create(loc, leftIsResult, rightIsNan); + mlir::arith::OrIOp::create(builder, loc, leftIsResult, rightIsNan); } else if constexpr (behavior == ExtremumBehavior::IeeeMinMaximum) { // Always return NaNs if one the input is NaNs auto leftIsResult = - builder.create(loc, orderedCmp, left, right); - auto leftIsNan = builder.create( - loc, mlir::arith::CmpFPredicate::UNE, left, left); - result = builder.create(loc, leftIsResult, leftIsNan); + mlir::arith::CmpFOp::create(builder, loc, orderedCmp, left, right); + auto leftIsNan = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::UNE, left, left); + result = + mlir::arith::OrIOp::create(builder, loc, leftIsResult, leftIsNan); } else if constexpr (behavior == ExtremumBehavior::MinMaxss) { // If the left is a NaN, return the right whatever it is. result = - builder.create(loc, orderedCmp, left, right); + mlir::arith::CmpFOp::create(builder, loc, orderedCmp, left, right); } else if constexpr (behavior == ExtremumBehavior::PgfortranLlvm) { // If one of the operand is a NaN, return left whatever it is. static constexpr auto unorderedCmp = extremum == Extremum::Max ? mlir::arith::CmpFPredicate::UGT : mlir::arith::CmpFPredicate::ULT; result = - builder.create(loc, unorderedCmp, left, right); + mlir::arith::CmpFOp::create(builder, loc, unorderedCmp, left, right); } else { // TODO: ieeeMinNum/ieeeMaxNum static_assert(behavior == ExtremumBehavior::IeeeMinMaxNum, @@ -8814,8 +8879,8 @@ static mlir::Value createExtremumCompare(mlir::Location loc, left = builder.createConvert(loc, signlessType, left); right = builder.createConvert(loc, signlessType, right); } - result = - builder.create(loc, integerPredicate, left, right); + result = mlir::arith::CmpIOp::create(builder, loc, integerPredicate, left, + right); } else if (fir::isa_char(type) || fir::isa_char(fir::unwrapRefType(type))) { // TODO: ! character min and max is tricky because the result // length is the length of the longest argument! @@ -8936,13 +9001,14 @@ IntrinsicLibrary::genVerify(mlir::Type resultType, builder.getContext(), builder.getKindMap().defaultLogicalKind()); mlir::Value temp = builder.createTemporary(loc, logTy); mlir::Value castb = builder.createConvert(loc, logTy, b); - builder.create(loc, castb, temp); + fir::StoreOp::create(builder, loc, castb, temp); return builder.createBox(loc, temp); }; - mlir::Value back = fir::isUnboxedValue(args[2]) - ? makeRefThenEmbox(*args[2].getUnboxed()) - : builder.create( - loc, fir::BoxType::get(builder.getI1Type())); + mlir::Value back = + fir::isUnboxedValue(args[2]) + ? makeRefThenEmbox(*args[2].getUnboxed()) + : fir::AbsentOp::create(builder, loc, + fir::BoxType::get(builder.getI1Type())); // Handle required string argument mlir::Value string = builder.createBox(loc, args[0]); @@ -8982,8 +9048,8 @@ IntrinsicLibrary::genExtremumloc(FN func, FD funcDim, llvm::StringRef errMsg, // Handle optional mask argument auto mask = isStaticallyAbsent(args[2]) - ? builder.create( - loc, fir::BoxType::get(builder.getI1Type())) + ? fir::AbsentOp::create( + builder, loc, fir::BoxType::get(builder.getI1Type())) : builder.createBox(loc, args[2]); // Handle optional kind argument @@ -9065,8 +9131,8 @@ IntrinsicLibrary::genExtremumVal(FN func, FD funcDim, FC funcChar, // Handle optional mask argument auto mask = isStaticallyAbsent(args[2]) - ? builder.create( - loc, fir::BoxType::get(builder.getI1Type())) + ? fir::AbsentOp::create( + builder, loc, fir::BoxType::get(builder.getI1Type())) : builder.createBox(loc, args[2]); bool absentDim = isStaticallyAbsent(args[1]); @@ -9130,7 +9196,7 @@ mlir::Value IntrinsicLibrary::genExtremum(mlir::Type, for (auto arg : args.drop_front()) { mlir::Value mask = createExtremumCompare(loc, builder, result, arg); - result = builder.create(loc, mask, result, arg); + result = mlir::arith::SelectOp::create(builder, loc, mask, result, arg); } return result; } diff --git a/flang/lib/Optimizer/Builder/LowLevelIntrinsics.cpp b/flang/lib/Optimizer/Builder/LowLevelIntrinsics.cpp index 64d70d70829fb..3fb7fab099965 100644 --- a/flang/lib/Optimizer/Builder/LowLevelIntrinsics.cpp +++ b/flang/lib/Optimizer/Builder/LowLevelIntrinsics.cpp @@ -31,8 +31,7 @@ mlir::func::FuncOp fir::factory::getRealloc(fir::FirOpBuilder &builder) { mlir::func::FuncOp fir::factory::getLlvmGetRounding(fir::FirOpBuilder &builder) { auto int32Ty = builder.getIntegerType(32); - auto funcTy = - mlir::FunctionType::get(builder.getContext(), std::nullopt, {int32Ty}); + auto funcTy = mlir::FunctionType::get(builder.getContext(), {}, {int32Ty}); return builder.createFunction(builder.getUnknownLoc(), "llvm.get.rounding", funcTy); } @@ -40,8 +39,7 @@ fir::factory::getLlvmGetRounding(fir::FirOpBuilder &builder) { mlir::func::FuncOp fir::factory::getLlvmSetRounding(fir::FirOpBuilder &builder) { auto int32Ty = builder.getIntegerType(32); - auto funcTy = - mlir::FunctionType::get(builder.getContext(), {int32Ty}, std::nullopt); + auto funcTy = mlir::FunctionType::get(builder.getContext(), {int32Ty}, {}); return builder.createFunction(builder.getUnknownLoc(), "llvm.set.rounding", funcTy); } @@ -49,8 +47,8 @@ fir::factory::getLlvmSetRounding(fir::FirOpBuilder &builder) { mlir::func::FuncOp fir::factory::getLlvmInitTrampoline(fir::FirOpBuilder &builder) { auto ptrTy = builder.getRefType(builder.getIntegerType(8)); - auto funcTy = mlir::FunctionType::get(builder.getContext(), - {ptrTy, ptrTy, ptrTy}, std::nullopt); + auto funcTy = + mlir::FunctionType::get(builder.getContext(), {ptrTy, ptrTy, ptrTy}, {}); return builder.createFunction(builder.getUnknownLoc(), "llvm.init.trampoline", funcTy); } @@ -90,8 +88,7 @@ mlir::func::FuncOp fir::factory::getFeenableexcept(fir::FirOpBuilder &builder) { mlir::func::FuncOp fir::factory::getFegetexcept(fir::FirOpBuilder &builder) { auto int32Ty = builder.getIntegerType(32); - auto funcTy = - mlir::FunctionType::get(builder.getContext(), std::nullopt, {int32Ty}); + auto funcTy = mlir::FunctionType::get(builder.getContext(), {}, {int32Ty}); return builder.createFunction(builder.getUnknownLoc(), "fegetexcept", funcTy); } diff --git a/flang/lib/Optimizer/Builder/MutableBox.cpp b/flang/lib/Optimizer/Builder/MutableBox.cpp index d944a4c98473e..50c945df5b465 100644 --- a/flang/lib/Optimizer/Builder/MutableBox.cpp +++ b/flang/lib/Optimizer/Builder/MutableBox.cpp @@ -35,7 +35,7 @@ createNewFirBox(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value shape; if (!extents.empty()) { if (lbounds.empty()) { - shape = builder.create(loc, extents); + shape = fir::ShapeOp::create(builder, loc, extents); } else { llvm::SmallVector shapeShiftBounds; for (auto [lb, extent] : llvm::zip(lbounds, extents)) { @@ -44,8 +44,8 @@ createNewFirBox(fir::FirOpBuilder &builder, mlir::Location loc, } auto shapeShiftType = fir::ShapeShiftType::get(builder.getContext(), extents.size()); - shape = builder.create(loc, shapeShiftType, - shapeShiftBounds); + shape = fir::ShapeShiftOp::create(builder, loc, shapeShiftType, + shapeShiftBounds); } } // Otherwise, this a scalar. Leave the shape empty. @@ -78,8 +78,8 @@ createNewFirBox(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value emptySlice; auto boxType = fir::updateTypeWithVolatility( box.getBoxTy(), fir::isa_volatile_type(cleanedAddr.getType())); - return builder.create(loc, boxType, cleanedAddr, shape, - emptySlice, cleanedLengths, tdesc); + return fir::EmboxOp::create(builder, loc, boxType, cleanedAddr, shape, + emptySlice, cleanedLengths, tdesc); } //===----------------------------------------------------------------------===// @@ -106,7 +106,7 @@ class MutablePropertyReader { bool forceIRBoxRead = false) : builder{builder}, loc{loc}, box{box} { if (forceIRBoxRead || !box.isDescribedByVariables()) - irBox = builder.create(loc, box.getAddr()); + irBox = fir::LoadOp::create(builder, loc, box.getAddr()); } /// Get base address of allocated/associated entity. mlir::Value readBaseAddress() { @@ -114,10 +114,10 @@ class MutablePropertyReader { auto memrefTy = box.getBoxTy().getEleTy(); if (!fir::isa_ref_type(memrefTy)) memrefTy = builder.getRefType(memrefTy); - return builder.create(loc, memrefTy, irBox); + return fir::BoxAddrOp::create(builder, loc, memrefTy, irBox); } auto addrVar = box.getMutableProperties().addr; - return builder.create(loc, addrVar); + return fir::LoadOp::create(builder, loc, addrVar); } /// Return {lbound, extent} values read from the MutableBoxValue given /// the dimension. @@ -125,13 +125,14 @@ class MutablePropertyReader { auto idxTy = builder.getIndexType(); if (irBox) { auto dimVal = builder.createIntegerConstant(loc, idxTy, dim); - auto dimInfo = builder.create(loc, idxTy, idxTy, idxTy, - irBox, dimVal); + auto dimInfo = fir::BoxDimsOp::create(builder, loc, idxTy, idxTy, idxTy, + irBox, dimVal); return {dimInfo.getResult(0), dimInfo.getResult(1)}; } const auto &mutableProperties = box.getMutableProperties(); - auto lb = builder.create(loc, mutableProperties.lbounds[dim]); - auto ext = builder.create(loc, mutableProperties.extents[dim]); + auto lb = fir::LoadOp::create(builder, loc, mutableProperties.lbounds[dim]); + auto ext = + fir::LoadOp::create(builder, loc, mutableProperties.extents[dim]); return {lb, ext}; } @@ -146,7 +147,7 @@ class MutablePropertyReader { const auto &deferred = box.getMutableProperties().deferredParams; if (deferred.empty()) fir::emitFatalError(loc, "allocatable entity has no length property"); - return builder.create(loc, deferred[0]); + return fir::LoadOp::create(builder, loc, deferred[0]); } /// Read and return all extents. If \p lbounds vector is provided, lbounds are @@ -223,7 +224,7 @@ class MutablePropertyWriter { /// all that can be described in the new fir.box (e.g. non contiguous entity). void updateWithIrBox(mlir::Value newBox) { assert(!box.isDescribedByVariables()); - builder.create(loc, newBox, box.getAddr()); + fir::StoreOp::create(builder, loc, newBox, box.getAddr()); } /// Set unallocated/disassociated status for the entity described by /// MutableBoxValue. Deallocation is not performed by this helper. @@ -231,8 +232,8 @@ class MutablePropertyWriter { if (box.isDescribedByVariables()) { auto addrVar = box.getMutableProperties().addr; auto nullTy = fir::dyn_cast_ptrEleTy(addrVar.getType()); - builder.create(loc, builder.createNullConstant(loc, nullTy), - addrVar); + fir::StoreOp::create(builder, loc, + builder.createNullConstant(loc, nullTy), addrVar); } else { // Note that the dynamic type of polymorphic entities must be reset to the // declaration type of the mutable box. See Fortran 2018 7.8.2 NOTE 1. @@ -246,7 +247,7 @@ class MutablePropertyWriter { auto deallocatedBox = fir::factory::createUnallocatedBox( builder, loc, box.getBoxTy(), box.nonDeferredLenParams(), typeSourceBox, allocator); - builder.create(loc, deallocatedBox, box.getAddr()); + fir::StoreOp::create(builder, loc, deallocatedBox, box.getAddr()); } } @@ -286,7 +287,7 @@ class MutablePropertyWriter { const bool valueTypeIsVolatile = fir::isa_volatile_type(fir::unwrapRefType(box.getAddr().getType())); irBox = builder.createVolatileCast(loc, valueTypeIsVolatile, irBox); - builder.create(loc, irBox, box.getAddr()); + fir::StoreOp::create(builder, loc, irBox, box.getAddr()); } /// Update the set of property variables of the MutableBoxValue. @@ -295,8 +296,8 @@ class MutablePropertyWriter { mlir::ValueRange lengths) { auto castAndStore = [&](mlir::Value val, mlir::Value addr) { auto type = fir::dyn_cast_ptrEleTy(addr.getType()); - builder.create(loc, builder.createConvert(loc, type, val), - addr); + fir::StoreOp::create(builder, loc, builder.createConvert(loc, type, val), + addr); }; const auto &mutableProperties = box.getMutableProperties(); castAndStore(addr, mutableProperties.addr); @@ -379,8 +380,8 @@ mlir::Value fir::factory::createUnallocatedBox( } } mlir::Value emptySlice; - auto embox = builder.create( - loc, baseBoxType, nullAddr, shape, emptySlice, lenParams, typeSourceBox); + auto embox = fir::EmboxOp::create(builder, loc, baseBoxType, nullAddr, shape, + emptySlice, lenParams, typeSourceBox); if (allocator != 0) embox.setAllocatorIdx(allocator); if (isAssumedRank) @@ -459,7 +460,7 @@ fir::factory::genMutableBoxRead(fir::FirOpBuilder &builder, mlir::Location loc, } mlir::Value sourceBox; if (box.isPolymorphic()) - sourceBox = builder.create(loc, box.getAddr()); + sourceBox = fir::LoadOp::create(builder, loc, box.getAddr()); if (rank) return fir::ArrayBoxValue{addr, extents, lbounds, sourceBox}; if (box.isPolymorphic()) @@ -490,7 +491,7 @@ static void genFreemem(fir::FirOpBuilder &builder, mlir::Location loc, // so make sure the heap type is restored before deallocation. auto cast = builder.createConvert( loc, fir::HeapType::get(fir::dyn_cast_ptrEleTy(addr.getType())), addr); - builder.create(loc, cast); + fir::FreeMemOp::create(builder, loc, cast); } void fir::factory::genFreememIfAllocated(fir::FirOpBuilder &builder, @@ -498,8 +499,8 @@ void fir::factory::genFreememIfAllocated(fir::FirOpBuilder &builder, const fir::MutableBoxValue &box) { auto addr = MutablePropertyReader(builder, loc, box).readBaseAddress(); auto isAllocated = builder.genIsNotNullAddr(loc, addr); - auto ifOp = builder.create(loc, isAllocated, - /*withElseRegion=*/false); + auto ifOp = fir::IfOp::create(builder, loc, isAllocated, + /*withElseRegion=*/false); auto insPt = builder.saveInsertionPoint(); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); ::genFreemem(builder, loc, addr); @@ -521,23 +522,23 @@ void fir::factory::associateMutableBox(fir::FirOpBuilder &builder, mlir::Value sourceBox; if (auto *polyBox = source.getBoxOf()) sourceBox = polyBox->getSourceBox(); - writer.updateMutableBox(p.getAddr(), /*lbounds=*/std::nullopt, - /*extents=*/std::nullopt, - /*lengths=*/std::nullopt, sourceBox); + writer.updateMutableBox(p.getAddr(), /*lbounds=*/{}, + /*extents=*/{}, + /*lengths=*/{}, sourceBox); }, [&](const fir::UnboxedValue &addr) { - writer.updateMutableBox(addr, /*lbounds=*/std::nullopt, - /*extents=*/std::nullopt, - /*lengths=*/std::nullopt); + writer.updateMutableBox(addr, /*lbounds=*/{}, + /*extents=*/{}, + /*lengths=*/{}); }, [&](const fir::CharBoxValue &ch) { - writer.updateMutableBox(ch.getAddr(), /*lbounds=*/std::nullopt, - /*extents=*/std::nullopt, {ch.getLen()}); + writer.updateMutableBox(ch.getAddr(), /*lbounds=*/{}, + /*extents=*/{}, {ch.getLen()}); }, [&](const fir::ArrayBoxValue &arr) { writer.updateMutableBox(arr.getAddr(), lbounds.empty() ? arr.getLBounds() : lbounds, - arr.getExtents(), /*lengths=*/std::nullopt); + arr.getExtents(), /*lengths=*/{}); }, [&](const fir::CharArrayBoxValue &arr) { writer.updateMutableBox(arr.getAddr(), @@ -553,15 +554,15 @@ void fir::factory::associateMutableBox(fir::FirOpBuilder &builder, if (box.hasAssumedRank()) { assert(arr.hasAssumedRank() && "expect both arr and box to be assumed-rank"); - mlir::Value reboxed = builder.create( - loc, box.getBoxTy(), arr.getAddr(), + mlir::Value reboxed = fir::ReboxAssumedRankOp::create( + builder, loc, box.getBoxTy(), arr.getAddr(), fir::LowerBoundModifierAttribute::Preserve); writer.updateWithIrBox(reboxed); } else if (box.isDescribedByVariables()) { // LHS is a contiguous pointer described by local variables. Open RHS // fir.box to update the LHS. - auto rawAddr = builder.create(loc, arr.getMemTy(), - arr.getAddr()); + auto rawAddr = fir::BoxAddrOp::create(builder, loc, arr.getMemTy(), + arr.getAddr()); auto extents = fir::factory::getExtents(loc, builder, source); llvm::SmallVector lenParams; if (arr.isCharacter()) { @@ -576,11 +577,11 @@ void fir::factory::associateMutableBox(fir::FirOpBuilder &builder, if (!newLbounds.empty()) { auto shiftType = fir::ShiftType::get(builder.getContext(), newLbounds.size()); - shift = builder.create(loc, shiftType, newLbounds); + shift = fir::ShiftOp::create(builder, loc, shiftType, newLbounds); } auto reboxed = - builder.create(loc, box.getBoxTy(), arr.getAddr(), - shift, /*slice=*/mlir::Value()); + fir::ReboxOp::create(builder, loc, box.getBoxTy(), arr.getAddr(), + shift, /*slice=*/mlir::Value()); writer.updateWithIrBox(reboxed); } }, @@ -608,9 +609,9 @@ void fir::factory::associateMutableBoxWithRemap( for (auto [lb, ub] : llvm::zip(lbounds, ubounds)) { auto lbi = builder.createConvert(loc, idxTy, lb); auto ubi = builder.createConvert(loc, idxTy, ub); - auto diff = builder.create(loc, idxTy, ubi, lbi); + auto diff = mlir::arith::SubIOp::create(builder, loc, idxTy, ubi, lbi); extents.emplace_back( - builder.create(loc, idxTy, diff, one)); + mlir::arith::AddIOp::create(builder, loc, idxTy, diff, one)); } } else { // lbounds are default. Upper bounds and extents are the same. @@ -634,11 +635,11 @@ void fir::factory::associateMutableBoxWithRemap( source.match( [&](const fir::PolymorphicValue &p) { writer.updateMutableBox(cast(p.getAddr()), lbounds, extents, - /*lengths=*/std::nullopt); + /*lengths=*/{}); }, [&](const fir::UnboxedValue &addr) { writer.updateMutableBox(cast(addr), lbounds, extents, - /*lengths=*/std::nullopt); + /*lengths=*/{}); }, [&](const fir::CharBoxValue &ch) { writer.updateMutableBox(cast(ch.getAddr()), lbounds, extents, @@ -646,7 +647,7 @@ void fir::factory::associateMutableBoxWithRemap( }, [&](const fir::ArrayBoxValue &arr) { writer.updateMutableBox(cast(arr.getAddr()), lbounds, extents, - /*lengths=*/std::nullopt); + /*lengths=*/{}); }, [&](const fir::CharArrayBoxValue &arr) { writer.updateMutableBox(cast(arr.getAddr()), lbounds, extents, @@ -657,8 +658,8 @@ void fir::factory::associateMutableBoxWithRemap( if (box.isDescribedByVariables()) { // LHS is a contiguous pointer described by local variables. Open RHS // fir.box to update the LHS. - auto rawAddr = builder.create(loc, arr.getMemTy(), - arr.getAddr()); + auto rawAddr = fir::BoxAddrOp::create(builder, loc, arr.getMemTy(), + arr.getAddr()); llvm::SmallVector lenParams; if (arr.isCharacter()) { lenParams.emplace_back( @@ -678,10 +679,10 @@ void fir::factory::associateMutableBoxWithRemap( shapeArgs.push_back(ext); } auto shape = - builder.create(loc, shapeType, shapeArgs); + fir::ShapeShiftOp::create(builder, loc, shapeType, shapeArgs); auto reboxed = - builder.create(loc, box.getBoxTy(), arr.getAddr(), - shape, /*slice=*/mlir::Value()); + fir::ReboxOp::create(builder, loc, box.getBoxTy(), arr.getAddr(), + shape, /*slice=*/mlir::Value()); writer.updateWithIrBox(reboxed); } }, @@ -748,15 +749,15 @@ static mlir::Value allocateAndInitNewStorage(fir::FirOpBuilder &builder, mlir::ValueRange lenParams, llvm::StringRef allocName) { auto lengths = getNewLengths(builder, loc, box, lenParams); - auto newStorage = builder.create( - loc, box.getBaseTy(), allocName, lengths, extents); + auto newStorage = fir::AllocMemOp::create(builder, loc, box.getBaseTy(), + allocName, lengths, extents); if (mlir::isa(box.getEleTy())) { // TODO: skip runtime initialization if this is not required. Currently, // there is no way to know here if a derived type needs it or not. But the // information is available at compile time and could be reflected here // somehow. - mlir::Value irBox = createNewFirBox(builder, loc, box, newStorage, - std::nullopt, extents, lengths); + mlir::Value irBox = + createNewFirBox(builder, loc, box, newStorage, {}, extents, lengths); fir::runtime::genDerivedTypeInitialize(builder, loc, irBox); } return newStorage; @@ -771,8 +772,8 @@ void fir::factory::genInlinedAllocation( llvm::SmallVector safeExtents; for (mlir::Value extent : extents) safeExtents.push_back(fir::factory::genMaxWithZero(builder, loc, extent)); - auto heap = builder.create(loc, box.getBaseTy(), allocName, - lengths, safeExtents); + auto heap = fir::AllocMemOp::create(builder, loc, box.getBaseTy(), allocName, + lengths, safeExtents); MutablePropertyWriter{builder, loc, box}.updateMutableBox( heap, lbounds, safeExtents, lengths); if (mlir::isa(box.getEleTy())) { @@ -841,10 +842,11 @@ fir::factory::MutableBoxReallocation fir::factory::genReallocIfNeeded( mlir::Value required) { auto castPrevious = builder.createConvert(loc, required.getType(), previous); - auto cmp = builder.create( - loc, mlir::arith::CmpIPredicate::ne, castPrevious, required); - mustReallocate = builder.create( - loc, cmp, cmp, mustReallocate); + auto cmp = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::ne, castPrevious, + required); + mustReallocate = mlir::arith::SelectOp::create( + builder, loc, cmp, cmp, mustReallocate); }; llvm::SmallVector previousExtents = reader.readShape(); if (!shape.empty()) @@ -879,17 +881,17 @@ fir::factory::MutableBoxReallocation fir::factory::genReallocIfNeeded( ".auto.alloc"); if (storageHandler) storageHandler(getExtValForStorage(heap)); - builder.create(loc, heap); + fir::ResultOp::create(builder, loc, heap); }) .genElse([&]() { if (storageHandler) storageHandler(getExtValForStorage(addr)); - builder.create(loc, addr); + fir::ResultOp::create(builder, loc, addr); }); ifOp.end(); auto newAddr = ifOp.getResults()[0]; - builder.create( - loc, mlir::ValueRange{mustReallocate, newAddr}); + fir::ResultOp::create(builder, loc, + mlir::ValueRange{mustReallocate, newAddr}); }) .genElse([&]() { auto trueValue = builder.createBool(loc, true); @@ -900,15 +902,15 @@ fir::factory::MutableBoxReallocation fir::factory::genReallocIfNeeded( builder, loc, "array left hand side must be allocated when the right hand " "side is a scalar"); - builder.create(loc, - mlir::ValueRange{trueValue, addr}); + fir::ResultOp::create(builder, loc, + mlir::ValueRange{trueValue, addr}); } else { auto heap = allocateAndInitNewStorage( builder, loc, box, shape, lengthParams, ".auto.alloc"); if (storageHandler) storageHandler(getExtValForStorage(heap)); - builder.create(loc, - mlir::ValueRange{trueValue, heap}); + fir::ResultOp::create(builder, loc, + mlir::ValueRange{trueValue, heap}); } }); ifOp.end(); @@ -976,7 +978,7 @@ mlir::Value fir::factory::genNullBoxStorage(fir::FirOpBuilder &builder, mlir::Value boxStorage = builder.createTemporary(loc, boxTy); mlir::Value nullBox = fir::factory::createUnallocatedBox( builder, loc, boxTy, /*nonDeferredParams=*/{}); - builder.create(loc, nullBox, boxStorage); + fir::StoreOp::create(builder, loc, nullBox, boxStorage); return boxStorage; } @@ -988,11 +990,11 @@ mlir::Value fir::factory::getAndEstablishBoxStorage( mlir::Value nullAddr = builder.createNullConstant(loc, boxTy.getBaseAddressType()); mlir::Value box = - builder.create(loc, boxTy, nullAddr, shape, - /*emptySlice=*/mlir::Value{}, - fir::factory::elideLengthsAlreadyInType( - boxTy.unwrapInnerType(), typeParams), - polymorphicMold); - builder.create(loc, box, boxStorage); + fir::EmboxOp::create(builder, loc, boxTy, nullAddr, shape, + /*emptySlice=*/mlir::Value{}, + fir::factory::elideLengthsAlreadyInType( + boxTy.unwrapInnerType(), typeParams), + polymorphicMold); + fir::StoreOp::create(builder, loc, box, boxStorage); return boxStorage; } diff --git a/flang/lib/Optimizer/Builder/PPCIntrinsicCall.cpp b/flang/lib/Optimizer/Builder/PPCIntrinsicCall.cpp index 0094ce892d61b..03952da95b11e 100644 --- a/flang/lib/Optimizer/Builder/PPCIntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/PPCIntrinsicCall.cpp @@ -17,6 +17,7 @@ #include "flang/Evaluate/common.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/MutableBox.h" +#include "mlir/Dialect/Index/IR/IndexOps.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" namespace fir { @@ -1090,7 +1091,7 @@ void PPCIntrinsicLibrary::genMtfsf(llvm::ArrayRef args) { builder.getContext(), builder); funcOp = builder.createFunction(loc, "llvm.ppc.mtfsf", libFuncType); } - builder.create(loc, funcOp, scalarArgs); + fir::CallOp::create(builder, loc, funcOp, scalarArgs); } // VEC_ABS @@ -1117,7 +1118,7 @@ PPCIntrinsicLibrary::genVecAbs(mlir::Type resultType, } funcOp = builder.createFunction(loc, fname, ftype); - auto callOp{builder.create(loc, funcOp, argBases[0])}; + auto callOp{fir::CallOp::create(builder, loc, funcOp, argBases[0])}; return callOp.getResult(0); } else if (auto eleTy = mlir::dyn_cast(vTypeInfo.eleTy)) { // vec_abs(arg1) = max(0 - arg1, arg1) @@ -1127,8 +1128,8 @@ PPCIntrinsicLibrary::genVecAbs(mlir::Type resultType, // construct vector(0,..) auto zeroVal{builder.createIntegerConstant(loc, eleTy, 0)}; auto vZero{ - builder.create(loc, newVecTy, zeroVal)}; - auto zeroSubVarg1{builder.create(loc, vZero, varg1)}; + mlir::vector::BroadcastOp::create(builder, loc, newVecTy, zeroVal)}; + auto zeroSubVarg1{mlir::arith::SubIOp::create(builder, loc, vZero, varg1)}; mlir::func::FuncOp funcOp{nullptr}; switch (eleTy.getWidth()) { @@ -1158,7 +1159,7 @@ PPCIntrinsicLibrary::genVecAbs(mlir::Type resultType, funcOp = builder.createFunction(loc, fname, ftype); mlir::Value args[] = {zeroSubVarg1, varg1}; - auto callOp{builder.create(loc, funcOp, args)}; + auto callOp{fir::CallOp::create(builder, loc, funcOp, args)}; return builder.createConvert(loc, argBases[0].getType(), callOp.getResult(0)); } @@ -1188,21 +1189,21 @@ fir::ExtendedValue PPCIntrinsicLibrary::genVecAddAndMulSubXor( switch (vop) { case VecOp::Add: if (isInteger) - r = builder.create(loc, vargs[0], vargs[1]); + r = mlir::arith::AddIOp::create(builder, loc, vargs[0], vargs[1]); else if (isFloat) - r = builder.create(loc, vargs[0], vargs[1]); + r = mlir::arith::AddFOp::create(builder, loc, vargs[0], vargs[1]); break; case VecOp::Mul: if (isInteger) - r = builder.create(loc, vargs[0], vargs[1]); + r = mlir::arith::MulIOp::create(builder, loc, vargs[0], vargs[1]); else if (isFloat) - r = builder.create(loc, vargs[0], vargs[1]); + r = mlir::arith::MulFOp::create(builder, loc, vargs[0], vargs[1]); break; case VecOp::Sub: if (isInteger) - r = builder.create(loc, vargs[0], vargs[1]); + r = mlir::arith::SubIOp::create(builder, loc, vargs[0], vargs[1]); else if (isFloat) - r = builder.create(loc, vargs[0], vargs[1]); + r = mlir::arith::SubFOp::create(builder, loc, vargs[0], vargs[1]); break; case VecOp::And: case VecOp::Xor: { @@ -1216,16 +1217,16 @@ fir::ExtendedValue PPCIntrinsicLibrary::genVecAddAndMulSubXor( auto wd{mlir::dyn_cast(vecTyInfo.eleTy).getWidth()}; auto ftype{builder.getIntegerType(wd)}; auto bcVecTy{mlir::VectorType::get(vecTyInfo.len, ftype)}; - arg1 = builder.create(loc, bcVecTy, vargs[0]); - arg2 = builder.create(loc, bcVecTy, vargs[1]); + arg1 = mlir::vector::BitCastOp::create(builder, loc, bcVecTy, vargs[0]); + arg2 = mlir::vector::BitCastOp::create(builder, loc, bcVecTy, vargs[1]); } if (vop == VecOp::And) - r = builder.create(loc, arg1, arg2); + r = mlir::arith::AndIOp::create(builder, loc, arg1, arg2); else if (vop == VecOp::Xor) - r = builder.create(loc, arg1, arg2); + r = mlir::arith::XOrIOp::create(builder, loc, arg1, arg2); if (isFloat) - r = builder.create(loc, vargs[0].getType(), r); + r = mlir::vector::BitCastOp::create(builder, loc, vargs[0].getType(), r); break; } @@ -1341,7 +1342,7 @@ PPCIntrinsicLibrary::genVecAnyCompare(mlir::Type resultType, assert((!fname.empty() && ftype) && "invalid type"); mlir::func::FuncOp funcOp{builder.createFunction(loc, fname, ftype)}; - auto callOp{builder.create(loc, funcOp, cmpArgs)}; + auto callOp{fir::CallOp::create(builder, loc, funcOp, cmpArgs)}; return callOp.getResult(0); } @@ -1472,7 +1473,7 @@ PPCIntrinsicLibrary::genVecCmp(mlir::Type resultType, // arg1 < arg2 --> vcmpgt(arg2, arg1) mlir::Value vargs[]{argBases[argOrder[vop][0]], argBases[argOrder[vop][1]]}; - auto callOp{builder.create(loc, funcOp, vargs)}; + auto callOp{fir::CallOp::create(builder, loc, funcOp, vargs)}; res = callOp.getResult(0); break; } @@ -1486,14 +1487,15 @@ PPCIntrinsicLibrary::genVecCmp(mlir::Type resultType, // Construct a constant vector(-1) auto negOneVal{builder.createIntegerConstant( loc, getConvertedElementType(context, eTy), -1)}; - auto vNegOne{builder.create( - loc, vecTyInfo.toMlirVectorType(context), negOneVal)}; + auto vNegOne{mlir::vector::BroadcastOp::create( + builder, loc, vecTyInfo.toMlirVectorType(context), negOneVal)}; - auto callOp{builder.create(loc, funcOp, vargs)}; + auto callOp{fir::CallOp::create(builder, loc, funcOp, vargs)}; mlir::Value callRes{callOp.getResult(0)}; auto vargs2{ convertVecArgs(builder, loc, vecTyInfo, mlir::ValueRange{callRes})}; - auto xorRes{builder.create(loc, vargs2[0], vNegOne)}; + auto xorRes{ + mlir::arith::XOrIOp::create(builder, loc, vargs2[0], vNegOne)}; res = builder.createConvert(loc, returnType, xorRes); break; @@ -1518,7 +1520,7 @@ PPCIntrinsicLibrary::genVecCmp(mlir::Type resultType, default: llvm_unreachable("Invalid vector operation for generator"); } - auto callOp{builder.create(loc, funcOp, vargs)}; + auto callOp{fir::CallOp::create(builder, loc, funcOp, vargs)}; res = callOp.getResult(0); } else llvm_unreachable("invalid vector type"); @@ -1534,13 +1536,13 @@ static inline mlir::Value swapVectorWordPairs(fir::FirOpBuilder &builder, auto vtype{mlir::VectorType::get(16, mlir::IntegerType::get(context, 8))}; if (ty != vtype) - arg = builder.create(loc, vtype, arg).getResult(); + arg = mlir::LLVM::BitcastOp::create(builder, loc, vtype, arg).getResult(); llvm::SmallVector mask{4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15, 8, 9, 10, 11}; - arg = builder.create(loc, arg, arg, mask); + arg = mlir::vector::ShuffleOp::create(builder, loc, arg, arg, mask); if (ty != vtype) - arg = builder.create(loc, ty, arg); + arg = mlir::LLVM::BitcastOp::create(builder, loc, ty, arg); return arg; } @@ -1575,7 +1577,7 @@ PPCIntrinsicLibrary::genVecConvert(mlir::Type resultType, : "llvm.ppc.altivec.vcfsx"}; auto funcOp{builder.createFunction(loc, fname, ftype)}; mlir::Value newArgs[] = {argBases[0], convArg}; - auto callOp{builder.create(loc, funcOp, newArgs)}; + auto callOp{fir::CallOp::create(builder, loc, funcOp, newArgs)}; return callOp.getResult(0); } else if (width == 64) { @@ -1584,8 +1586,8 @@ PPCIntrinsicLibrary::genVecConvert(mlir::Type resultType, // vec_vtf(arg1, arg2) = fmul(1.0 / (1 << arg2), llvm.sitofp(arg1)) auto convOp{(isUnsigned) - ? builder.create(loc, ty, vArg1) - : builder.create(loc, ty, vArg1)}; + ? mlir::LLVM::UIToFPOp::create(builder, loc, ty, vArg1) + : mlir::LLVM::SIToFPOp::create(builder, loc, ty, vArg1)}; // construct vector<1./(1< auto constInt{mlir::dyn_cast_or_null( @@ -1594,11 +1596,11 @@ PPCIntrinsicLibrary::genVecConvert(mlir::Type resultType, assert(constInt && "expected integer constant argument"); double f{1.0 / (1 << constInt.getInt())}; llvm::SmallVector vals{f, f}; - auto constOp{builder.create( - loc, ty, builder.getF64VectorAttr(vals))}; + auto constOp{mlir::arith::ConstantOp::create( + builder, loc, ty, builder.getF64VectorAttr(vals))}; - auto mulOp{builder.create( - loc, ty, convOp->getResult(0), constOp)}; + auto mulOp{mlir::LLVM::FMulOp::create(builder, loc, ty, + convOp->getResult(0), constOp)}; return builder.createConvert(loc, fir::VectorType::get(2, fTy), mulOp); } @@ -1612,7 +1614,7 @@ PPCIntrinsicLibrary::genVecConvert(mlir::Type resultType, auto firTy{resTyInfo.toFirVectorType()}; // vec_convert(v, mold) = bitcast v to "type of mold" - auto conv{builder.create(loc, moldTy, vArg1)}; + auto conv{mlir::LLVM::BitcastOp::create(builder, loc, moldTy, vArg1)}; return builder.createConvert(loc, firTy, conv); } @@ -1628,7 +1630,7 @@ PPCIntrinsicLibrary::genVecConvert(mlir::Type resultType, auto ftype{ genFuncType, Ty::RealVector<4>>(context, builder)}; auto funcOp{builder.createFunction(loc, fname, ftype)}; - auto callOp{builder.create(loc, funcOp, newArgs)}; + auto callOp{fir::CallOp::create(builder, loc, funcOp, newArgs)}; return callOp.getResult(0); } else if (vecTyInfo.isFloat64()) { @@ -1637,7 +1639,7 @@ PPCIntrinsicLibrary::genVecConvert(mlir::Type resultType, genFuncType, Ty::RealVector<8>>(context, builder)}; auto funcOp{builder.createFunction(loc, fname, ftype)}; newArgs[0] = - builder.create(loc, funcOp, newArgs).getResult(0); + fir::CallOp::create(builder, loc, funcOp, newArgs).getResult(0); auto fvf32Ty{newArgs[0].getType()}; auto f32type{mlir::Float32Type::get(context)}; auto mvf32Ty{mlir::VectorType::get(4, f32type)}; @@ -1661,7 +1663,7 @@ static mlir::Value convertVectorElementOrder(fir::FirOpBuilder &builder, mlir::Value idx) { mlir::Value numSub1{ builder.createIntegerConstant(loc, idx.getType(), vecInfo.len - 1)}; - return builder.create(loc, idx.getType(), numSub1, idx); + return mlir::LLVM::SubOp::create(builder, loc, idx.getType(), numSub1, idx); } // VEC_EXTRACT @@ -1680,12 +1682,14 @@ PPCIntrinsicLibrary::genVecExtract(mlir::Type resultType, // position auto numEle{builder.createIntegerConstant(loc, argTypes[1], vecTyInfo.len)}; mlir::Value uremOp{ - builder.create(loc, argBases[1], numEle)}; + mlir::LLVM::URemOp::create(builder, loc, argBases[1], numEle)}; if (!isNativeVecElemOrderOnLE()) uremOp = convertVectorElementOrder(builder, loc, vecTyInfo, uremOp); - return builder.create(loc, varg0, uremOp); + mlir::Value index = builder.createOrFold( + loc, builder.getIndexType(), uremOp); + return mlir::vector::ExtractOp::create(builder, loc, varg0, index); } // VEC_INSERT @@ -1701,14 +1705,16 @@ PPCIntrinsicLibrary::genVecInsert(mlir::Type resultType, auto numEle{builder.createIntegerConstant(loc, argTypes[2], vecTyInfo.len)}; mlir::Value uremOp{ - builder.create(loc, argBases[2], numEle)}; + mlir::LLVM::URemOp::create(builder, loc, argBases[2], numEle)}; if (!isNativeVecElemOrderOnLE()) uremOp = convertVectorElementOrder(builder, loc, vecTyInfo, uremOp); - auto res{builder.create(loc, argBases[0], - varg1, uremOp)}; - return builder.create(loc, vecTyInfo.toFirVectorType(), res); + mlir::Value index = builder.createOrFold( + loc, builder.getIndexType(), uremOp); + mlir::Value res = + mlir::vector::InsertOp::create(builder, loc, argBases[0], varg1, index); + return fir::ConvertOp::create(builder, loc, vecTyInfo.toFirVectorType(), res); } // VEC_MERGEH, VEC_MERGEL @@ -1794,8 +1800,8 @@ PPCIntrinsicLibrary::genVecMerge(mlir::Type resultType, llvm::SmallVector &mergeMask = (isBEVecElemOrderOnLE()) ? rMask : mMask; - auto callOp{builder.create(loc, vargs[0], vargs[1], - mergeMask)}; + auto callOp{mlir::vector::ShuffleOp::create(builder, loc, vargs[0], vargs[1], + mergeMask)}; return builder.createConvert(loc, resultType, callOp); } @@ -1807,9 +1813,9 @@ static mlir::Value addOffsetToAddress(fir::FirOpBuilder &builder, auto arrRefTy{builder.getRefType(fir::SequenceType::get( {typeExtent}, mlir::IntegerType::get(builder.getContext(), 8)))}; // Convert arg to !fir.ref> - auto resAddr{builder.create(loc, arrRefTy, baseAddr)}; + auto resAddr{fir::ConvertOp::create(builder, loc, arrRefTy, baseAddr)}; - return builder.create(loc, arrRefTy, resAddr, offset); + return fir::CoordinateOp::create(builder, loc, arrRefTy, resAddr, offset); } static mlir::Value reverseVectorElements(fir::FirOpBuilder &builder, @@ -1821,8 +1827,8 @@ static mlir::Value reverseVectorElements(fir::FirOpBuilder &builder, for (int64_t i = 0; i < len; ++i) { mask.push_back(len - 1 - i); } - auto undefVec{builder.create(loc, v.getType())}; - return builder.create(loc, v, undefVec, mask); + auto undefVec{fir::UndefOp::create(builder, loc, v.getType())}; + return mlir::vector::ShuffleOp::create(builder, loc, v, undefVec, mask); } static mlir::NamedAttribute getAlignmentAttr(fir::FirOpBuilder &builder, @@ -1871,8 +1877,8 @@ fir::ExtendedValue PPCIntrinsicLibrary::genVecLdNoCallGrp( const auto triple{fir::getTargetTriple(builder.getModule())}; // Need to get align 1. - auto result{builder.create(loc, mlirTy, addr, - getAlignmentAttr(builder, 1))}; + auto result{fir::LoadOp::create(builder, loc, mlirTy, addr, + getAlignmentAttr(builder, 1))}; if ((vop == VecOp::Xl && isBEVecElemOrderOnLE()) || (vop == VecOp::Xlbe && triple.isLittleEndian())) return builder.createConvert( @@ -1965,13 +1971,13 @@ PPCIntrinsicLibrary::genVecLdCallGrp(mlir::Type resultType, mlir::FunctionType::get(context, {addr.getType()}, {intrinResTy})}; auto funcOp{builder.createFunction(loc, fname, funcType)}; auto result{ - builder.create(loc, funcOp, parsedArgs).getResult(0)}; + fir::CallOp::create(builder, loc, funcOp, parsedArgs).getResult(0)}; if (vop == VecOp::Lxvp) return result; if (intrinResTy != mlirTy) - result = builder.create(loc, mlirTy, result); + result = mlir::vector::BitCastOp::create(builder, loc, mlirTy, result); if (vop != VecOp::Xld2 && vop != VecOp::Xlw4 && isBEVecElemOrderOnLE()) return builder.createConvert( @@ -1998,13 +2004,13 @@ PPCIntrinsicLibrary::genVecLvsGrp(mlir::Type resultType, // Convert arg0 to i64 type if needed auto i64ty{mlir::IntegerType::get(context, 64)}; if (arg0.getType() != i64ty) - arg0 = builder.create(loc, i64ty, arg0); + arg0 = fir::ConvertOp::create(builder, loc, i64ty, arg0); // offset is modulo 16, so shift left 56 bits and then right 56 bits to clear // upper 56 bit while preserving sign auto shiftVal{builder.createIntegerConstant(loc, i64ty, 56)}; - auto offset{builder.create(loc, arg0, shiftVal)}; - auto offset2{builder.create(loc, offset, shiftVal)}; + auto offset{mlir::arith::ShLIOp::create(builder, loc, arg0, shiftVal)}; + auto offset2{mlir::arith::ShRSIOp::create(builder, loc, offset, shiftVal)}; // Add the offsetArg to %addr of arg1 auto addr{addOffsetToAddress(builder, loc, arg1, offset2)}; @@ -2024,7 +2030,7 @@ PPCIntrinsicLibrary::genVecLvsGrp(mlir::Type resultType, auto funcType{mlir::FunctionType::get(context, {addr.getType()}, {mlirTy})}; auto funcOp{builder.createFunction(loc, fname, funcType)}; auto result{ - builder.create(loc, funcOp, parsedArgs).getResult(0)}; + fir::CallOp::create(builder, loc, funcOp, parsedArgs).getResult(0)}; if (isNativeVecElemOrderOnLE()) return builder.createConvert( @@ -2061,19 +2067,19 @@ PPCIntrinsicLibrary::genVecNmaddMsub(mlir::Type resultType, std::get<1>(fmaMap[width]))}; if (vop == VecOp::Nmadd) { // vec_nmadd(arg1, arg2, arg3) = -fma(arg1, arg2, arg3) - auto callOp{builder.create(loc, funcOp, newArgs)}; + auto callOp{fir::CallOp::create(builder, loc, funcOp, newArgs)}; // We need to convert fir.vector to MLIR vector to use fneg and then back // to fir.vector to store. auto vCall{builder.createConvert(loc, vTypeInfo.toMlirVectorType(context), callOp.getResult(0))}; - auto neg{builder.create(loc, vCall)}; + auto neg{mlir::arith::NegFOp::create(builder, loc, vCall)}; return builder.createConvert(loc, vTypeInfo.toFirVectorType(), neg); } else if (vop == VecOp::Msub) { // vec_msub(arg1, arg2, arg3) = fma(arg1, arg2, -arg3) - newArgs[2] = builder.create(loc, newArgs[2]); + newArgs[2] = mlir::arith::NegFOp::create(builder, loc, newArgs[2]); - auto callOp{builder.create(loc, funcOp, newArgs)}; + auto callOp{fir::CallOp::create(builder, loc, funcOp, newArgs)}; return callOp.getResult(0); } llvm_unreachable("Invalid vector operation for generator"); @@ -2104,10 +2110,10 @@ PPCIntrinsicLibrary::genVecPerm(mlir::Type resultType, auto mMask{builder.createConvert(loc, mlirMaskTy, argBases[2])}; if (mlirTy != vi32Ty) { - mArg0 = - builder.create(loc, vi32Ty, mArg0).getResult(); - mArg1 = - builder.create(loc, vi32Ty, mArg1).getResult(); + mArg0 = mlir::LLVM::BitcastOp::create(builder, loc, vi32Ty, mArg0) + .getResult(); + mArg1 = mlir::LLVM::BitcastOp::create(builder, loc, vi32Ty, mArg1) + .getResult(); } auto funcOp{builder.createFunction( @@ -2122,23 +2128,23 @@ PPCIntrinsicLibrary::genVecPerm(mlir::Type resultType, auto v8Ty{mlir::VectorType::get(16, i8Ty)}; auto negOne{builder.createMinusOneInteger(loc, i8Ty)}; auto vNegOne{ - builder.create(loc, v8Ty, negOne)}; + mlir::vector::BroadcastOp::create(builder, loc, v8Ty, negOne)}; - mMask = builder.create(loc, mMask, vNegOne); + mMask = mlir::arith::XOrIOp::create(builder, loc, mMask, vNegOne); newArgs = {mArg1, mArg0, mMask}; } else { newArgs = {mArg0, mArg1, mMask}; } - auto res{builder.create(loc, funcOp, newArgs).getResult(0)}; + auto res{fir::CallOp::create(builder, loc, funcOp, newArgs).getResult(0)}; if (res.getType() != argTypes[0]) { // fir.call llvm.ppc.altivec.vperm returns !fir.vector // convert the result back to the original type res = builder.createConvert(loc, vi32Ty, res); if (mlirTy != vi32Ty) - res = - builder.create(loc, mlirTy, res).getResult(); + res = mlir::LLVM::BitcastOp::create(builder, loc, mlirTy, res) + .getResult(); } return builder.createConvert(loc, resultType, res); } @@ -2151,10 +2157,10 @@ PPCIntrinsicLibrary::genVecPerm(mlir::Type resultType, auto constInt{constIntOp.getInt()}; // arg1, arg2, and result type share same VecTypeInfo if (vecTyInfo.isFloat()) { - mArg0 = - builder.create(loc, vf64Ty, mArg0).getResult(); - mArg1 = - builder.create(loc, vf64Ty, mArg1).getResult(); + mArg0 = mlir::LLVM::BitcastOp::create(builder, loc, vf64Ty, mArg0) + .getResult(); + mArg1 = mlir::LLVM::BitcastOp::create(builder, loc, vf64Ty, mArg1) + .getResult(); } llvm::SmallVector nMask; // native vector element order mask @@ -2183,9 +2189,9 @@ PPCIntrinsicLibrary::genVecPerm(mlir::Type resultType, llvm::SmallVector mask = (isBEVecElemOrderOnLE()) ? rMask : nMask; - auto res{builder.create(loc, mArg0, mArg1, mask)}; + auto res{mlir::vector::ShuffleOp::create(builder, loc, mArg0, mArg1, mask)}; if (res.getType() != mlirTy) { - auto cast{builder.create(loc, mlirTy, res)}; + auto cast{mlir::LLVM::BitcastOp::create(builder, loc, mlirTy, res)}; return builder.createConvert(loc, resultType, cast); } return builder.createConvert(loc, resultType, res); @@ -2212,22 +2218,23 @@ PPCIntrinsicLibrary::genVecSel(mlir::Type resultType, // construct a constant <16 x i8> vector with value -1 for bitcast auto bcVecTy{mlir::VectorType::get(16, i8Ty)}; - auto vNegOne{builder.create(loc, bcVecTy, negOne)}; + auto vNegOne{ + mlir::vector::BroadcastOp::create(builder, loc, bcVecTy, negOne)}; // bitcast arguments to bcVecTy - auto arg1{builder.create(loc, bcVecTy, vargs[0])}; - auto arg2{builder.create(loc, bcVecTy, vargs[1])}; - auto arg3{builder.create(loc, bcVecTy, vargs[2])}; + auto arg1{mlir::vector::BitCastOp::create(builder, loc, bcVecTy, vargs[0])}; + auto arg2{mlir::vector::BitCastOp::create(builder, loc, bcVecTy, vargs[1])}; + auto arg3{mlir::vector::BitCastOp::create(builder, loc, bcVecTy, vargs[2])}; // vec_sel(arg1, arg2, arg3) = // (arg2 and arg3) or (arg1 and (arg3 xor vector(-1,...))) - auto comp{builder.create(loc, arg3, vNegOne)}; - auto a1AndComp{builder.create(loc, arg1, comp)}; - auto a1OrA2{builder.create(loc, arg2, arg3)}; - auto res{builder.create(loc, a1AndComp, a1OrA2)}; + auto comp{mlir::arith::XOrIOp::create(builder, loc, arg3, vNegOne)}; + auto a1AndComp{mlir::arith::AndIOp::create(builder, loc, arg1, comp)}; + auto a1OrA2{mlir::arith::AndIOp::create(builder, loc, arg2, arg3)}; + auto res{mlir::arith::OrIOp::create(builder, loc, a1AndComp, a1OrA2)}; auto bcRes{ - builder.create(loc, vargs[0].getType(), res)}; + mlir::vector::BitCastOp::create(builder, loc, vargs[0].getType(), res)}; return builder.createConvert(loc, vecTyInfos[0].toFirVectorType(), bcRes); } @@ -2264,14 +2271,14 @@ PPCIntrinsicLibrary::genVecShift(mlir::Type resultType, auto vecVal{builder.createIntegerConstant( loc, getConvertedElementType(context, vecTyInfoArgs[0].eleTy), width)}; auto mask{ - builder.create(loc, mlirTyArgs[1], vecVal)}; - auto shft{builder.create(loc, mlirVecArgs[1], mask)}; + mlir::vector::BroadcastOp::create(builder, loc, mlirTyArgs[1], vecVal)}; + auto shft{mlir::arith::RemUIOp::create(builder, loc, mlirVecArgs[1], mask)}; mlir::Value res{nullptr}; if (vop == VecOp::Sr) - res = builder.create(loc, mlirVecArgs[0], shft); + res = mlir::arith::ShRUIOp::create(builder, loc, mlirVecArgs[0], shft); else if (vop == VecOp::Sl) - res = builder.create(loc, mlirVecArgs[0], shft); + res = mlir::arith::ShLIOp::create(builder, loc, mlirVecArgs[0], shft); shftRes = builder.createConvert(loc, argTypes[0], res); } else if (vop == VecOp::Sll || vop == VecOp::Slo || vop == VecOp::Srl || @@ -2281,11 +2288,11 @@ PPCIntrinsicLibrary::genVecShift(mlir::Type resultType, // Bitcast to vector<4xi32> auto bcVecTy{mlir::VectorType::get(4, builder.getIntegerType(32))}; if (mlirTyArgs[0] != bcVecTy) - mlirVecArgs[0] = - builder.create(loc, bcVecTy, mlirVecArgs[0]); + mlirVecArgs[0] = mlir::vector::BitCastOp::create(builder, loc, bcVecTy, + mlirVecArgs[0]); if (mlirTyArgs[1] != bcVecTy) - mlirVecArgs[1] = - builder.create(loc, bcVecTy, mlirVecArgs[1]); + mlirVecArgs[1] = mlir::vector::BitCastOp::create(builder, loc, bcVecTy, + mlirVecArgs[1]); llvm::StringRef funcName; switch (vop) { @@ -2307,13 +2314,13 @@ PPCIntrinsicLibrary::genVecShift(mlir::Type resultType, auto funcTy{genFuncType, Ty::IntegerVector<4>, Ty::IntegerVector<4>>(context, builder)}; mlir::func::FuncOp funcOp{builder.createFunction(loc, funcName, funcTy)}; - auto callOp{builder.create(loc, funcOp, mlirVecArgs)}; + auto callOp{fir::CallOp::create(builder, loc, funcOp, mlirVecArgs)}; // If the result vector type is different from the original type, need // to convert to mlir vector, bitcast and then convert back to fir vector. if (callOp.getResult(0).getType() != argTypes[0]) { auto res = builder.createConvert(loc, bcVecTy, callOp.getResult(0)); - res = builder.create(loc, mlirTyArgs[0], res); + res = mlir::vector::BitCastOp::create(builder, loc, mlirTyArgs[0], res); shftRes = builder.createConvert(loc, argTypes[0], res); } else { shftRes = callOp.getResult(0); @@ -2329,10 +2336,10 @@ PPCIntrinsicLibrary::genVecShift(mlir::Type resultType, auto vi8Ty{mlir::VectorType::get(16, builder.getIntegerType(8))}; if (mlirTyArgs[0] != vi8Ty) { mlirVecArgs[0] = - builder.create(loc, vi8Ty, mlirVecArgs[0]) + mlir::LLVM::BitcastOp::create(builder, loc, vi8Ty, mlirVecArgs[0]) .getResult(); mlirVecArgs[1] = - builder.create(loc, vi8Ty, mlirVecArgs[1]) + mlir::LLVM::BitcastOp::create(builder, loc, vi8Ty, mlirVecArgs[1]) .getResult(); } @@ -2347,19 +2354,19 @@ PPCIntrinsicLibrary::genVecShift(mlir::Type resultType, if (triple.isLittleEndian()) { for (int i = 16; i < 32; ++i) mask.push_back(i - shiftVal); - shftRes = builder.create(loc, mlirVecArgs[1], - mlirVecArgs[0], mask); + shftRes = mlir::vector::ShuffleOp::create(builder, loc, mlirVecArgs[1], + mlirVecArgs[0], mask); } else { for (int i = 0; i < 16; ++i) mask.push_back(i + shiftVal); - shftRes = builder.create(loc, mlirVecArgs[0], - mlirVecArgs[1], mask); + shftRes = mlir::vector::ShuffleOp::create(builder, loc, mlirVecArgs[0], + mlirVecArgs[1], mask); } // Bitcast to the original type if (shftRes.getType() != mlirTyArgs[0]) shftRes = - builder.create(loc, mlirTyArgs[0], shftRes); + mlir::LLVM::BitcastOp::create(builder, loc, mlirTyArgs[0], shftRes); return builder.createConvert(loc, resultType, shftRes); } else @@ -2384,8 +2391,9 @@ PPCIntrinsicLibrary::genVecSplat(mlir::Type resultType, auto vecTyInfo{getVecTypeFromFir(argBases[0])}; auto extractOp{genVecExtract(resultType, args)}; - splatOp = builder.create( - loc, *(extractOp.getUnboxed()), vecTyInfo.toMlirVectorType(context)); + splatOp = + mlir::vector::SplatOp::create(builder, loc, *(extractOp.getUnboxed()), + vecTyInfo.toMlirVectorType(context)); retTy = vecTyInfo.toFirVectorType(); break; } @@ -2393,8 +2401,8 @@ PPCIntrinsicLibrary::genVecSplat(mlir::Type resultType, assert(args.size() == 1); auto vecTyInfo{getVecTypeFromEle(argBases[0])}; - splatOp = builder.create( - loc, argBases[0], vecTyInfo.toMlirVectorType(context)); + splatOp = mlir::vector::SplatOp::create( + builder, loc, argBases[0], vecTyInfo.toMlirVectorType(context)); retTy = vecTyInfo.toFirVectorType(); break; } @@ -2404,8 +2412,8 @@ PPCIntrinsicLibrary::genVecSplat(mlir::Type resultType, auto intOp{builder.createConvert(loc, eleTy, argBases[0])}; // the intrinsic always returns vector(integer(4)) - splatOp = builder.create( - loc, intOp, mlir::VectorType::get(4, eleTy)); + splatOp = mlir::vector::SplatOp::create(builder, loc, intOp, + mlir::VectorType::get(4, eleTy)); retTy = fir::VectorType::get(4, eleTy); break; } @@ -2433,14 +2441,14 @@ PPCIntrinsicLibrary::genVecXlds(mlir::Type resultType, auto i64Ty{mlir::IntegerType::get(builder.getContext(), 64)}; auto i64VecTy{mlir::VectorType::get(2, i64Ty)}; auto i64RefTy{builder.getRefType(i64Ty)}; - auto addrConv{builder.create(loc, i64RefTy, addr)}; + auto addrConv{fir::ConvertOp::create(builder, loc, i64RefTy, addr)}; - auto addrVal{builder.create(loc, addrConv)}; - auto splatRes{builder.create(loc, addrVal, i64VecTy)}; + auto addrVal{fir::LoadOp::create(builder, loc, addrConv)}; + auto splatRes{mlir::vector::SplatOp::create(builder, loc, addrVal, i64VecTy)}; mlir::Value result{nullptr}; if (mlirTy != splatRes.getType()) { - result = builder.create(loc, mlirTy, splatRes); + result = mlir::vector::BitCastOp::create(builder, loc, mlirTy, splatRes); } else result = splatRes; @@ -2790,7 +2798,7 @@ void PPCIntrinsicLibrary::genMmaIntr(llvm::ArrayRef args) { if (i == 0 && HandlerOp == MMAHandlerOp::FirstArgIsResult) { // First argument is passed in as an address. We need to load // the content to match the LLVM interface. - v = builder.create(loc, v); + v = fir::LoadOp::create(builder, loc, v); } auto vType{v.getType()}; mlir::Type targetType{intrFuncType.getInput(j)}; @@ -2801,7 +2809,7 @@ void PPCIntrinsicLibrary::genMmaIntr(llvm::ArrayRef args) { auto len{mlir::dyn_cast(vType).getLen()}; mlir::VectorType mlirType = mlir::VectorType::get(len, eleTy); auto v0{builder.createConvert(loc, mlirType, v)}; - auto v1{builder.create(loc, targetType, v0)}; + auto v1{mlir::vector::BitCastOp::create(builder, loc, targetType, v0)}; intrArgs.push_back(v1); } else if (mlir::isa(targetType) && mlir::isa(vType)) { @@ -2817,7 +2825,7 @@ void PPCIntrinsicLibrary::genMmaIntr(llvm::ArrayRef args) { intrArgs.push_back(v); } } - auto callSt{builder.create(loc, funcOp, intrArgs)}; + auto callSt{fir::CallOp::create(builder, loc, funcOp, intrArgs)}; if (HandlerOp == MMAHandlerOp::SubToFunc || HandlerOp == MMAHandlerOp::SubToFuncReverseArgOnLE || HandlerOp == MMAHandlerOp::FirstArgIsResult) { @@ -2826,10 +2834,11 @@ void PPCIntrinsicLibrary::genMmaIntr(llvm::ArrayRef args) { mlir::Value destPtr{fir::getBase(args[0])}; mlir::Type callResultPtrType{builder.getRefType(callResult.getType())}; if (destPtr.getType() != callResultPtrType) { - destPtr = builder.create(loc, callResultPtrType, destPtr); + destPtr = + fir::ConvertOp::create(builder, loc, callResultPtrType, destPtr); } // Copy the result. - builder.create(loc, callResult, destPtr); + fir::StoreOp::create(builder, loc, callResult, destPtr); } } @@ -2896,7 +2905,7 @@ void PPCIntrinsicLibrary::genVecStore(llvm::ArrayRef args) { if (vop == VecOp::Stxvp) { biArgs.push_back(argBases[0]); biArgs.push_back(addr); - builder.create(loc, funcOp, biArgs); + fir::CallOp::create(builder, loc, funcOp, biArgs); return; } @@ -2906,7 +2915,7 @@ void PPCIntrinsicLibrary::genVecStore(llvm::ArrayRef args) { mlir::Value newArg1{nullptr}; if (stTy != arg1TyInfo.toMlirVectorType(context)) - newArg1 = builder.create(loc, stTy, cnv); + newArg1 = mlir::vector::BitCastOp::create(builder, loc, stTy, cnv); else newArg1 = cnv; @@ -2917,7 +2926,7 @@ void PPCIntrinsicLibrary::genVecStore(llvm::ArrayRef args) { biArgs.push_back(newArg1); biArgs.push_back(addr); - builder.create(loc, funcOp, biArgs); + fir::CallOp::create(builder, loc, funcOp, biArgs); } // VEC_XST, VEC_XST_BE, VEC_STXV, VEC_XSTD2, VEC_XSTW4 @@ -2966,7 +2975,7 @@ void PPCIntrinsicLibrary::genVecXStore( mlir::Type srcTy{nullptr}; if (numElem != arg1TyInfo.len) { - cnv = builder.create(loc, mlirVecTy, cnv); + cnv = mlir::vector::BitCastOp::create(builder, loc, mlirVecTy, cnv); srcTy = firVecTy; } else { srcTy = arg1TyInfo.toFirVectorType(); @@ -2989,9 +2998,9 @@ void PPCIntrinsicLibrary::genVecXStore( default: assert(false && "Invalid vector operation for generator"); } - builder.create(loc, mlir::TypeRange{}, - mlir::ValueRange{src, trg}, - getAlignmentAttr(builder, 1)); + fir::StoreOp::create(builder, loc, mlir::TypeRange{}, + mlir::ValueRange{src, trg}, + getAlignmentAttr(builder, 1)); } } // namespace fir diff --git a/flang/lib/Optimizer/Builder/Runtime/Allocatable.cpp b/flang/lib/Optimizer/Builder/Runtime/Allocatable.cpp index cd5f1f6d098c3..cc9f8280a172c 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Allocatable.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Allocatable.cpp @@ -30,7 +30,7 @@ mlir::Value fir::runtime::genMoveAlloc(fir::FirOpBuilder &builder, mlir::dyn_cast(fir::dyn_cast_ptrEleTy(from.getType())); mlir::Type derivedType = fir::unwrapInnerType(clTy.getEleTy()); declaredTypeDesc = - builder.create(loc, mlir::TypeAttr::get(derivedType)); + fir::TypeDescOp::create(builder, loc, mlir::TypeAttr::get(derivedType)); } else { declaredTypeDesc = builder.createNullConstant(loc); } @@ -38,7 +38,7 @@ mlir::Value fir::runtime::genMoveAlloc(fir::FirOpBuilder &builder, builder, loc, fTy, to, from, declaredTypeDesc, hasStat, errMsg, sourceFile, sourceLine)}; - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } void fir::runtime::genAllocatableApplyMold(fir::FirOpBuilder &builder, @@ -52,7 +52,7 @@ void fir::runtime::genAllocatableApplyMold(fir::FirOpBuilder &builder, builder.createIntegerConstant(loc, fTy.getInput(2), rank); llvm::SmallVector args{ fir::runtime::createArguments(builder, loc, fTy, desc, mold, rankVal)}; - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void fir::runtime::genAllocatableSetBounds(fir::FirOpBuilder &builder, @@ -66,7 +66,7 @@ void fir::runtime::genAllocatableSetBounds(fir::FirOpBuilder &builder, mlir::FunctionType fTy{func.getFunctionType()}; llvm::SmallVector args{fir::runtime::createArguments( builder, loc, fTy, desc, dimIndex, lowerBound, upperBound)}; - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void fir::runtime::genAllocatableAllocate(fir::FirOpBuilder &builder, @@ -84,10 +84,10 @@ void fir::runtime::genAllocatableAllocate(fir::FirOpBuilder &builder, hasStat = builder.createBool(loc, false); if (!errMsg) { mlir::Type boxNoneTy = fir::BoxType::get(builder.getNoneType()); - errMsg = builder.create(loc, boxNoneTy).getResult(); + errMsg = fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); } llvm::SmallVector args{ fir::runtime::createArguments(builder, loc, fTy, desc, asyncObject, hasStat, errMsg, sourceFile, sourceLine)}; - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } diff --git a/flang/lib/Optimizer/Builder/Runtime/ArrayConstructor.cpp b/flang/lib/Optimizer/Builder/Runtime/ArrayConstructor.cpp index 0d56cd2edc99b..8c9825efaaa4e 100644 --- a/flang/lib/Optimizer/Builder/Runtime/ArrayConstructor.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/ArrayConstructor.cpp @@ -50,7 +50,7 @@ mlir::Value fir::runtime::genInitArrayConstructorVector( auto args = fir::runtime::createArguments(builder, loc, funcType, cookie, toBox, useValueLengthParameters, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); return cookie; } @@ -63,7 +63,7 @@ void fir::runtime::genPushArrayConstructorValue( mlir::FunctionType funcType = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, funcType, arrayConstructorVector, fromBox); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void fir::runtime::genPushArrayConstructorSimpleScalar( @@ -75,5 +75,5 @@ void fir::runtime::genPushArrayConstructorSimpleScalar( mlir::FunctionType funcType = func.getFunctionType(); auto args = fir::runtime::createArguments( builder, loc, funcType, arrayConstructorVector, fromAddress); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } diff --git a/flang/lib/Optimizer/Builder/Runtime/Assign.cpp b/flang/lib/Optimizer/Builder/Runtime/Assign.cpp index 62f03f7d48665..336dbdc89c04a 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Assign.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Assign.cpp @@ -22,7 +22,7 @@ void fir::runtime::genAssign(fir::FirOpBuilder &builder, mlir::Location loc, fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); auto args = fir::runtime::createArguments(builder, loc, fTy, destBox, sourceBox, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void fir::runtime::genAssignPolymorphic(fir::FirOpBuilder &builder, @@ -36,7 +36,7 @@ void fir::runtime::genAssignPolymorphic(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); auto args = fir::runtime::createArguments(builder, loc, fTy, destBox, sourceBox, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void fir::runtime::genAssignExplicitLengthCharacter(fir::FirOpBuilder &builder, @@ -52,7 +52,7 @@ void fir::runtime::genAssignExplicitLengthCharacter(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); auto args = fir::runtime::createArguments(builder, loc, fTy, destBox, sourceBox, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void fir::runtime::genAssignTemporary(fir::FirOpBuilder &builder, @@ -66,7 +66,7 @@ void fir::runtime::genAssignTemporary(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); auto args = fir::runtime::createArguments(builder, loc, fTy, destBox, sourceBox, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void fir::runtime::genCopyInAssign(fir::FirOpBuilder &builder, @@ -79,7 +79,7 @@ void fir::runtime::genCopyInAssign(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); auto args = fir::runtime::createArguments(builder, loc, fTy, destBox, sourceBox, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void fir::runtime::genCopyOutAssign(fir::FirOpBuilder &builder, @@ -93,5 +93,5 @@ void fir::runtime::genCopyOutAssign(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); auto args = fir::runtime::createArguments(builder, loc, fTy, destBox, sourceBox, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } diff --git a/flang/lib/Optimizer/Builder/Runtime/CUDA/Descriptor.cpp b/flang/lib/Optimizer/Builder/Runtime/CUDA/Descriptor.cpp index 62a0652cc2e5d..a6ee98685f3c9 100644 --- a/flang/lib/Optimizer/Builder/Runtime/CUDA/Descriptor.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/CUDA/Descriptor.cpp @@ -30,7 +30,7 @@ void fir::runtime::cuda::genSyncGlobalDescriptor(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); llvm::SmallVector args{fir::runtime::createArguments( builder, loc, fTy, hostPtr, sourceFile, sourceLine)}; - builder.create(loc, callee, args); + fir::CallOp::create(builder, loc, callee, args); } void fir::runtime::cuda::genDescriptorCheckSection(fir::FirOpBuilder &builder, @@ -45,7 +45,7 @@ void fir::runtime::cuda::genDescriptorCheckSection(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); llvm::SmallVector args{fir::runtime::createArguments( builder, loc, fTy, desc, sourceFile, sourceLine)}; - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void fir::runtime::cuda::genSetAllocatorIndex(fir::FirOpBuilder &builder, @@ -60,5 +60,5 @@ void fir::runtime::cuda::genSetAllocatorIndex(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); llvm::SmallVector args{fir::runtime::createArguments( builder, loc, fTy, desc, index, sourceFile, sourceLine)}; - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } diff --git a/flang/lib/Optimizer/Builder/Runtime/Character.cpp b/flang/lib/Optimizer/Builder/Runtime/Character.cpp index b16819915d5ab..57fb0cccf6863 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Character.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Character.cpp @@ -34,7 +34,7 @@ static void genCharacterSearch(FN func, fir::FirOpBuilder &builder, auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, string1Box, string2Box, backBox, kind, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Helper function to recover the KIND from the FIR type. @@ -72,7 +72,7 @@ static void genAdjust(fir::FirOpBuilder &builder, mlir::Location loc, auto sourceFile = fir::factory::locationToFilename(builder, loc); auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, stringBox, sourceFile, sourceLine); - builder.create(loc, adjustFunc, args); + fir::CallOp::create(builder, loc, adjustFunc, args); } void fir::runtime::genAdjustL(fir::FirOpBuilder &builder, mlir::Location loc, @@ -114,9 +114,9 @@ fir::runtime::genCharCompare(fir::FirOpBuilder &builder, mlir::Location loc, auto fTy = beginFunc.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, fTy, lhsBuff, rhsBuff, lhsLen, rhsLen); - auto tri = builder.create(loc, beginFunc, args).getResult(0); + auto tri = fir::CallOp::create(builder, loc, beginFunc, args).getResult(0); auto zero = builder.createIntegerConstant(loc, tri.getType(), 0); - return builder.create(loc, cmp, tri, zero); + return mlir::arith::CmpIOp::create(builder, loc, cmp, tri, zero); } mlir::Value fir::runtime::genCharCompare(fir::FirOpBuilder &builder, @@ -130,8 +130,8 @@ mlir::Value fir::runtime::genCharCompare(fir::FirOpBuilder &builder, if (fir::isa_ref_type(base.getType())) return base; auto mem = - builder.create(loc, base.getType(), /*pinned=*/false); - builder.create(loc, base, mem); + fir::AllocaOp::create(builder, loc, base.getType(), /*pinned=*/false); + fir::StoreOp::create(builder, loc, base, mem); return mem; }; auto lhsBuffer = allocateIfNotInMemory(fir::getBase(lhs)); @@ -165,7 +165,7 @@ mlir::Value fir::runtime::genIndex(fir::FirOpBuilder &builder, auto args = fir::runtime::createArguments(builder, loc, fTy, stringBase, stringLen, substringBase, substringLen, back); - return builder.create(loc, indexFunc, args).getResult(0); + return fir::CallOp::create(builder, loc, indexFunc, args).getResult(0); } void fir::runtime::genIndexDescriptor(fir::FirOpBuilder &builder, @@ -189,7 +189,7 @@ void fir::runtime::genRepeat(fir::FirOpBuilder &builder, mlir::Location loc, auto args = fir::runtime::createArguments( builder, loc, fTy, resultBox, stringBox, ncopies, sourceFile, sourceLine); - builder.create(loc, repeatFunc, args); + fir::CallOp::create(builder, loc, repeatFunc, args); } void fir::runtime::genTrim(fir::FirOpBuilder &builder, mlir::Location loc, @@ -202,7 +202,7 @@ void fir::runtime::genTrim(fir::FirOpBuilder &builder, mlir::Location loc, auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, stringBox, sourceFile, sourceLine); - builder.create(loc, trimFunc, args); + fir::CallOp::create(builder, loc, trimFunc, args); } void fir::runtime::genScanDescriptor(fir::FirOpBuilder &builder, @@ -237,7 +237,7 @@ mlir::Value fir::runtime::genScan(fir::FirOpBuilder &builder, auto fTy = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, fTy, stringBase, stringLen, setBase, setLen, back); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } void fir::runtime::genVerifyDescriptor(fir::FirOpBuilder &builder, @@ -274,5 +274,5 @@ mlir::Value fir::runtime::genVerify(fir::FirOpBuilder &builder, auto fTy = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, fTy, stringBase, stringLen, setBase, setLen, back); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } diff --git a/flang/lib/Optimizer/Builder/Runtime/Command.cpp b/flang/lib/Optimizer/Builder/Runtime/Command.cpp index 35aa529a9a727..e65e2b6df7557 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Command.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Command.cpp @@ -30,7 +30,7 @@ mlir::Value fir::runtime::genCommandArgumentCount(fir::FirOpBuilder &builder, mlir::Location loc) { auto argumentCountFunc = fir::runtime::getRuntimeFunc(loc, builder); - return builder.create(loc, argumentCountFunc).getResult(0); + return fir::CallOp::create(builder, loc, argumentCountFunc).getResult(0); } mlir::Value fir::runtime::genGetCommand(fir::FirOpBuilder &builder, @@ -46,7 +46,7 @@ mlir::Value fir::runtime::genGetCommand(fir::FirOpBuilder &builder, llvm::SmallVector args = fir::runtime::createArguments(builder, loc, runtimeFuncTy, command, length, errmsg, sourceFile, sourceLine); - return builder.create(loc, runtimeFunc, args).getResult(0); + return fir::CallOp::create(builder, loc, runtimeFunc, args).getResult(0); } mlir::Value fir::runtime::genGetPID(fir::FirOpBuilder &builder, @@ -54,7 +54,7 @@ mlir::Value fir::runtime::genGetPID(fir::FirOpBuilder &builder, auto runtimeFunc = fir::runtime::getRuntimeFunc(loc, builder); - return builder.create(loc, runtimeFunc).getResult(0); + return fir::CallOp::create(builder, loc, runtimeFunc).getResult(0); } mlir::Value fir::runtime::genGetCommandArgument( @@ -69,7 +69,7 @@ mlir::Value fir::runtime::genGetCommandArgument( llvm::SmallVector args = fir::runtime::createArguments(builder, loc, runtimeFuncTy, number, value, length, errmsg, sourceFile, sourceLine); - return builder.create(loc, runtimeFunc, args).getResult(0); + return fir::CallOp::create(builder, loc, runtimeFunc, args).getResult(0); } mlir::Value fir::runtime::genGetEnvVariable(fir::FirOpBuilder &builder, @@ -87,7 +87,7 @@ mlir::Value fir::runtime::genGetEnvVariable(fir::FirOpBuilder &builder, llvm::SmallVector args = fir::runtime::createArguments( builder, loc, runtimeFuncTy, name, value, length, trimName, errmsg, sourceFile, sourceLine); - return builder.create(loc, runtimeFunc, args).getResult(0); + return fir::CallOp::create(builder, loc, runtimeFunc, args).getResult(0); } mlir::Value fir::runtime::genGetCwd(fir::FirOpBuilder &builder, @@ -100,7 +100,7 @@ mlir::Value fir::runtime::genGetCwd(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, runtimeFuncTy.getInput(2)); llvm::SmallVector args = fir::runtime::createArguments( builder, loc, runtimeFuncTy, cwd, sourceFile, sourceLine); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } mlir::Value fir::runtime::genHostnm(fir::FirOpBuilder &builder, @@ -113,7 +113,7 @@ mlir::Value fir::runtime::genHostnm(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, runtimeFuncTy.getInput(2)); llvm::SmallVector args = fir::runtime::createArguments( builder, loc, runtimeFuncTy, res, sourceFile, sourceLine); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } void fir::runtime::genPerror(fir::FirOpBuilder &builder, mlir::Location loc, @@ -123,7 +123,7 @@ void fir::runtime::genPerror(fir::FirOpBuilder &builder, mlir::Location loc, mlir::FunctionType runtimeFuncTy = runtimeFunc.getFunctionType(); llvm::SmallVector args = fir::runtime::createArguments(builder, loc, runtimeFuncTy, string); - builder.create(loc, runtimeFunc, args); + fir::CallOp::create(builder, loc, runtimeFunc, args); } mlir::Value fir::runtime::genPutEnv(fir::FirOpBuilder &builder, @@ -137,7 +137,7 @@ mlir::Value fir::runtime::genPutEnv(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, runtimeFuncTy.getInput(1)); llvm::SmallVector args = fir::runtime::createArguments( builder, loc, runtimeFuncTy, str, strLength, sourceFile, sourceLine); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } mlir::Value fir::runtime::genUnlink(fir::FirOpBuilder &builder, @@ -151,5 +151,5 @@ mlir::Value fir::runtime::genUnlink(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, runtimeFuncTy.getInput(1)); llvm::SmallVector args = fir::runtime::createArguments( builder, loc, runtimeFuncTy, path, pathLength, sourceFile, sourceLine); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } diff --git a/flang/lib/Optimizer/Builder/Runtime/Derived.cpp b/flang/lib/Optimizer/Builder/Runtime/Derived.cpp index 25b41518a90e5..1b0457bb2d0a1 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Derived.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Derived.cpp @@ -26,7 +26,7 @@ void fir::runtime::genDerivedTypeInitialize(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); auto args = fir::runtime::createArguments(builder, loc, fTy, box, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void fir::runtime::genDerivedTypeInitializeClone(fir::FirOpBuilder &builder, @@ -41,7 +41,7 @@ void fir::runtime::genDerivedTypeInitializeClone(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); auto args = fir::runtime::createArguments(builder, loc, fTy, newBox, box, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void fir::runtime::genDerivedTypeDestroy(fir::FirOpBuilder &builder, @@ -49,7 +49,7 @@ void fir::runtime::genDerivedTypeDestroy(fir::FirOpBuilder &builder, auto func = fir::runtime::getRuntimeFunc(loc, builder); auto fTy = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, fTy, box); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void fir::runtime::genDerivedTypeFinalize(fir::FirOpBuilder &builder, @@ -61,7 +61,7 @@ void fir::runtime::genDerivedTypeFinalize(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); auto args = fir::runtime::createArguments(builder, loc, fTy, box, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void fir::runtime::genDerivedTypeDestroyWithoutFinalization( @@ -70,7 +70,7 @@ void fir::runtime::genDerivedTypeDestroyWithoutFinalization( loc, builder); auto fTy = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, fTy, box); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void fir::runtime::genNullifyDerivedType(fir::FirOpBuilder &builder, @@ -78,7 +78,7 @@ void fir::runtime::genNullifyDerivedType(fir::FirOpBuilder &builder, fir::RecordType derivedType, unsigned rank) { mlir::Value typeDesc = - builder.create(loc, mlir::TypeAttr::get(derivedType)); + fir::TypeDescOp::create(builder, loc, mlir::TypeAttr::get(derivedType)); mlir::func::FuncOp callee = fir::runtime::getRuntimeFunc(loc, builder); @@ -90,7 +90,7 @@ void fir::runtime::genNullifyDerivedType(fir::FirOpBuilder &builder, mlir::Value c0 = builder.createIntegerConstant(loc, inputTypes[3], 0); args.push_back(rankCst); args.push_back(c0); - builder.create(loc, callee, args); + fir::CallOp::create(builder, loc, callee, args); } mlir::Value fir::runtime::genSameTypeAs(fir::FirOpBuilder &builder, @@ -100,7 +100,7 @@ mlir::Value fir::runtime::genSameTypeAs(fir::FirOpBuilder &builder, fir::runtime::getRuntimeFunc(loc, builder); auto fTy = sameTypeAsFunc.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, fTy, a, b); - return builder.create(loc, sameTypeAsFunc, args).getResult(0); + return fir::CallOp::create(builder, loc, sameTypeAsFunc, args).getResult(0); } mlir::Value fir::runtime::genExtendsTypeOf(fir::FirOpBuilder &builder, @@ -110,5 +110,6 @@ mlir::Value fir::runtime::genExtendsTypeOf(fir::FirOpBuilder &builder, fir::runtime::getRuntimeFunc(loc, builder); auto fTy = extendsTypeOfFunc.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, fTy, a, mold); - return builder.create(loc, extendsTypeOfFunc, args).getResult(0); + return fir::CallOp::create(builder, loc, extendsTypeOfFunc, args) + .getResult(0); } diff --git a/flang/lib/Optimizer/Builder/Runtime/EnvironmentDefaults.cpp b/flang/lib/Optimizer/Builder/Runtime/EnvironmentDefaults.cpp index bf5fd6af0eafa..fa3d00e8b844f 100755 --- a/flang/lib/Optimizer/Builder/Runtime/EnvironmentDefaults.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/EnvironmentDefaults.cpp @@ -44,7 +44,7 @@ mlir::Value fir::runtime::genEnvironmentDefaults( mlir::IntegerAttr one = builder.getIntegerAttr(idxTy, 1); std::string itemListName = envDefaultListPtrName + ".items"; auto listBuilder = [&](fir::FirOpBuilder &builder) { - mlir::Value list = builder.create(loc, itemListTy); + mlir::Value list = fir::UndefOp::create(builder, loc, itemListTy); llvm::SmallVector idx = {mlir::Attribute{}, mlir::Attribute{}}; auto insertStringField = [&](const std::string &s, @@ -52,8 +52,8 @@ mlir::Value fir::runtime::genEnvironmentDefaults( mlir::Value stringAddress = fir::getBase( fir::factory::createStringLiteral(builder, loc, s + '\0')); mlir::Value addr = builder.createConvert(loc, charRefTy, stringAddress); - return builder.create(loc, itemListTy, list, addr, - builder.getArrayAttr(idx)); + return fir::InsertValueOp::create(builder, loc, itemListTy, list, addr, + builder.getArrayAttr(idx)); }; size_t n = 0; @@ -65,7 +65,7 @@ mlir::Value fir::runtime::genEnvironmentDefaults( list = insertStringField(def.defaultValue, idx); ++n; } - builder.create(loc, list); + fir::HasValueOp::create(builder, loc, list); }; builder.createGlobalConstant(loc, itemListTy, itemListName, listBuilder, linkOnce); @@ -73,27 +73,27 @@ mlir::Value fir::runtime::genEnvironmentDefaults( // Define the EnviornmentDefaultList object. auto envDefaultListBuilder = [&](fir::FirOpBuilder &builder) { mlir::Value envDefaultList = - builder.create(loc, envDefaultListTy); + fir::UndefOp::create(builder, loc, envDefaultListTy); mlir::Value numItems = builder.createIntegerConstant(loc, intTy, envDefaults.size()); - envDefaultList = builder.create( - loc, envDefaultListTy, envDefaultList, numItems, - builder.getArrayAttr(zero)); + envDefaultList = fir::InsertValueOp::create(builder, loc, envDefaultListTy, + envDefaultList, numItems, + builder.getArrayAttr(zero)); fir::GlobalOp itemList = builder.getNamedGlobal(itemListName); assert(itemList && "missing environment default list"); - mlir::Value listAddr = builder.create( - loc, itemList.resultType(), itemList.getSymbol()); - envDefaultList = builder.create( - loc, envDefaultListTy, envDefaultList, listAddr, - builder.getArrayAttr(one)); - builder.create(loc, envDefaultList); + mlir::Value listAddr = fir::AddrOfOp::create( + builder, loc, itemList.resultType(), itemList.getSymbol()); + envDefaultList = fir::InsertValueOp::create(builder, loc, envDefaultListTy, + envDefaultList, listAddr, + builder.getArrayAttr(one)); + fir::HasValueOp::create(builder, loc, envDefaultList); }; fir::GlobalOp envDefaultList = builder.createGlobalConstant( loc, envDefaultListTy, envDefaultListPtrName + ".list", envDefaultListBuilder, linkOnce); // Define the pointer to the list used by the runtime. - mlir::Value addr = builder.create( - loc, envDefaultList.resultType(), envDefaultList.getSymbol()); + mlir::Value addr = fir::AddrOfOp::create( + builder, loc, envDefaultList.resultType(), envDefaultList.getSymbol()); return addr; } diff --git a/flang/lib/Optimizer/Builder/Runtime/Exceptions.cpp b/flang/lib/Optimizer/Builder/Runtime/Exceptions.cpp index 0f66315696ac7..0256644ed06e7 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Exceptions.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Exceptions.cpp @@ -18,21 +18,21 @@ mlir::Value fir::runtime::genMapExcept(fir::FirOpBuilder &builder, mlir::Value excepts) { mlir::func::FuncOp func{ fir::runtime::getRuntimeFunc(loc, builder)}; - return builder.create(loc, func, excepts).getResult(0); + return fir::CallOp::create(builder, loc, func, excepts).getResult(0); } void fir::runtime::genFeclearexcept(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value excepts) { mlir::func::FuncOp func{ fir::runtime::getRuntimeFunc(loc, builder)}; - builder.create(loc, func, excepts); + fir::CallOp::create(builder, loc, func, excepts); } void fir::runtime::genFeraiseexcept(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value excepts) { mlir::func::FuncOp func{ fir::runtime::getRuntimeFunc(loc, builder)}; - builder.create(loc, func, excepts); + fir::CallOp::create(builder, loc, func, excepts); } mlir::Value fir::runtime::genFetestexcept(fir::FirOpBuilder &builder, @@ -40,28 +40,28 @@ mlir::Value fir::runtime::genFetestexcept(fir::FirOpBuilder &builder, mlir::Value excepts) { mlir::func::FuncOp func{ fir::runtime::getRuntimeFunc(loc, builder)}; - return builder.create(loc, func, excepts).getResult(0); + return fir::CallOp::create(builder, loc, func, excepts).getResult(0); } void fir::runtime::genFedisableexcept(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value excepts) { mlir::func::FuncOp func{ fir::runtime::getRuntimeFunc(loc, builder)}; - builder.create(loc, func, excepts); + fir::CallOp::create(builder, loc, func, excepts); } void fir::runtime::genFeenableexcept(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value excepts) { mlir::func::FuncOp func{ fir::runtime::getRuntimeFunc(loc, builder)}; - builder.create(loc, func, excepts); + fir::CallOp::create(builder, loc, func, excepts); } mlir::Value fir::runtime::genFegetexcept(fir::FirOpBuilder &builder, mlir::Location loc) { mlir::func::FuncOp func{ fir::runtime::getRuntimeFunc(loc, builder)}; - return builder.create(loc, func).getResult(0); + return fir::CallOp::create(builder, loc, func).getResult(0); } mlir::Value fir::runtime::genSupportHalting(fir::FirOpBuilder &builder, @@ -69,33 +69,33 @@ mlir::Value fir::runtime::genSupportHalting(fir::FirOpBuilder &builder, mlir::Value excepts) { mlir::func::FuncOp func{ fir::runtime::getRuntimeFunc(loc, builder)}; - return builder.create(loc, func, excepts).getResult(0); + return fir::CallOp::create(builder, loc, func, excepts).getResult(0); } mlir::Value fir::runtime::genGetUnderflowMode(fir::FirOpBuilder &builder, mlir::Location loc) { mlir::func::FuncOp func{ fir::runtime::getRuntimeFunc(loc, builder)}; - return builder.create(loc, func).getResult(0); + return fir::CallOp::create(builder, loc, func).getResult(0); } void fir::runtime::genSetUnderflowMode(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value flag) { mlir::func::FuncOp func{ fir::runtime::getRuntimeFunc(loc, builder)}; - builder.create(loc, func, flag); + fir::CallOp::create(builder, loc, func, flag); } mlir::Value fir::runtime::genGetModesTypeSize(fir::FirOpBuilder &builder, mlir::Location loc) { mlir::func::FuncOp func{ fir::runtime::getRuntimeFunc(loc, builder)}; - return builder.create(loc, func).getResult(0); + return fir::CallOp::create(builder, loc, func).getResult(0); } mlir::Value fir::runtime::genGetStatusTypeSize(fir::FirOpBuilder &builder, mlir::Location loc) { mlir::func::FuncOp func{ fir::runtime::getRuntimeFunc(loc, builder)}; - return builder.create(loc, func).getResult(0); + return fir::CallOp::create(builder, loc, func).getResult(0); } diff --git a/flang/lib/Optimizer/Builder/Runtime/Execute.cpp b/flang/lib/Optimizer/Builder/Runtime/Execute.cpp index 71ee3996ac0da..2f85fb45ea0d2 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Execute.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Execute.cpp @@ -40,5 +40,5 @@ void fir::runtime::genExecuteCommandLine(fir::FirOpBuilder &builder, llvm::SmallVector args = fir::runtime::createArguments( builder, loc, runtimeFuncTy, command, wait, exitstat, cmdstat, cmdmsg, sourceFile, sourceLine); - builder.create(loc, runtimeFunc, args); + fir::CallOp::create(builder, loc, runtimeFunc, args); } diff --git a/flang/lib/Optimizer/Builder/Runtime/Inquiry.cpp b/flang/lib/Optimizer/Builder/Runtime/Inquiry.cpp index 718c3533564e8..5e3f022310973 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Inquiry.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Inquiry.cpp @@ -26,7 +26,7 @@ mlir::Value fir::runtime::genLboundDim(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); auto args = fir::runtime::createArguments(builder, loc, fTy, array, dim, sourceFile, sourceLine); - return builder.create(loc, lboundFunc, args).getResult(0); + return fir::CallOp::create(builder, loc, lboundFunc, args).getResult(0); } void fir::runtime::genLbound(fir::FirOpBuilder &builder, mlir::Location loc, @@ -40,7 +40,7 @@ void fir::runtime::genLbound(fir::FirOpBuilder &builder, mlir::Location loc, fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); auto args = fir::runtime::createArguments( builder, loc, fTy, resultAddr, array, kind, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Generate call to `Ubound` runtime routine. Calls to UBOUND with a DIM @@ -57,7 +57,7 @@ void fir::runtime::genUbound(fir::FirOpBuilder &builder, mlir::Location loc, fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, array, kind, sourceFile, sourceLine); - builder.create(loc, uboundFunc, args); + fir::CallOp::create(builder, loc, uboundFunc, args); } /// Generate call to `Size` runtime routine. This routine is a version when @@ -73,7 +73,7 @@ mlir::Value fir::runtime::genSizeDim(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); auto args = fir::runtime::createArguments(builder, loc, fTy, array, dim, sourceFile, sourceLine); - return builder.create(loc, sizeFunc, args).getResult(0); + return fir::CallOp::create(builder, loc, sizeFunc, args).getResult(0); } /// Generate call to `Size` runtime routine. This routine is a version when @@ -88,7 +88,7 @@ mlir::Value fir::runtime::genSize(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); auto args = fir::runtime::createArguments(builder, loc, fTy, array, sourceFile, sourceLine); - return builder.create(loc, sizeFunc, args).getResult(0); + return fir::CallOp::create(builder, loc, sizeFunc, args).getResult(0); } /// Generate call to `IsContiguous` runtime routine. @@ -99,7 +99,7 @@ mlir::Value fir::runtime::genIsContiguous(fir::FirOpBuilder &builder, fir::runtime::getRuntimeFunc(loc, builder); auto fTy = isContiguousFunc.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, fTy, array); - return builder.create(loc, isContiguousFunc, args).getResult(0); + return fir::CallOp::create(builder, loc, isContiguousFunc, args).getResult(0); } /// Generate call to `IsContiguousUpTo` runtime routine. @@ -111,7 +111,7 @@ mlir::Value fir::runtime::genIsContiguousUpTo(fir::FirOpBuilder &builder, fir::runtime::getRuntimeFunc(loc, builder); auto fTy = isContiguousFunc.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, fTy, array, dim); - return builder.create(loc, isContiguousFunc, args).getResult(0); + return fir::CallOp::create(builder, loc, isContiguousFunc, args).getResult(0); } void fir::runtime::genShape(fir::FirOpBuilder &builder, mlir::Location loc, @@ -125,5 +125,5 @@ void fir::runtime::genShape(fir::FirOpBuilder &builder, mlir::Location loc, fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); auto args = fir::runtime::createArguments( builder, loc, fTy, resultAddr, array, kind, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } diff --git a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp index 773d6408079cc..4b4954a3e738c 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp @@ -52,14 +52,15 @@ mlir::Value fir::runtime::genAssociated(fir::FirOpBuilder &builder, builder); llvm::SmallVector args = fir::runtime::createArguments( builder, loc, func.getFunctionType(), pointer, target); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } mlir::Value fir::runtime::genCpuTime(fir::FirOpBuilder &builder, mlir::Location loc) { mlir::func::FuncOp func = fir::runtime::getRuntimeFunc(loc, builder); - return builder.create(loc, func, std::nullopt).getResult(0); + return fir::CallOp::create(builder, loc, func, mlir::ValueRange{}) + .getResult(0); } void fir::runtime::genDateAndTime(fir::FirOpBuilder &builder, @@ -102,7 +103,7 @@ void fir::runtime::genDateAndTime(fir::FirOpBuilder &builder, llvm::SmallVector args = fir::runtime::createArguments( builder, loc, funcTy, dateBuffer, dateLen, timeBuffer, timeLen, zoneBuffer, zoneLen, sourceFile, sourceLine, values); - builder.create(loc, callee, args); + fir::CallOp::create(builder, loc, callee, args); } void fir::runtime::genEtime(fir::FirOpBuilder &builder, mlir::Location loc, @@ -116,7 +117,7 @@ void fir::runtime::genEtime(fir::FirOpBuilder &builder, mlir::Location loc, llvm::SmallVector args = fir::runtime::createArguments( builder, loc, runtimeFuncTy, values, time, sourceFile, sourceLine); - builder.create(loc, runtimeFunc, args); + fir::CallOp::create(builder, loc, runtimeFunc, args); } void fir::runtime::genFree(fir::FirOpBuilder &builder, mlir::Location loc, @@ -124,8 +125,8 @@ void fir::runtime::genFree(fir::FirOpBuilder &builder, mlir::Location loc, auto runtimeFunc = fir::runtime::getRuntimeFunc(loc, builder); mlir::Type intPtrTy = builder.getIntPtrType(); - builder.create(loc, runtimeFunc, - builder.createConvert(loc, intPtrTy, ptr)); + fir::CallOp::create(builder, loc, runtimeFunc, + builder.createConvert(loc, intPtrTy, ptr)); } mlir::Value fir::runtime::genFseek(fir::FirOpBuilder &builder, @@ -139,7 +140,7 @@ mlir::Value fir::runtime::genFseek(fir::FirOpBuilder &builder, llvm::SmallVector args = fir::runtime::createArguments(builder, loc, runtimeFuncTy, unit, offset, whence, sourceFile, sourceLine); - return builder.create(loc, runtimeFunc, args).getResult(0); + return fir::CallOp::create(builder, loc, runtimeFunc, args).getResult(0); ; } @@ -149,7 +150,7 @@ mlir::Value fir::runtime::genFtell(fir::FirOpBuilder &builder, mlir::FunctionType runtimeFuncTy = runtimeFunc.getFunctionType(); llvm::SmallVector args = fir::runtime::createArguments(builder, loc, runtimeFuncTy, unit); - return builder.create(loc, runtimeFunc, args).getResult(0); + return fir::CallOp::create(builder, loc, runtimeFunc, args).getResult(0); } mlir::Value fir::runtime::genGetGID(fir::FirOpBuilder &builder, @@ -157,7 +158,7 @@ mlir::Value fir::runtime::genGetGID(fir::FirOpBuilder &builder, auto runtimeFunc = fir::runtime::getRuntimeFunc(loc, builder); - return builder.create(loc, runtimeFunc).getResult(0); + return fir::CallOp::create(builder, loc, runtimeFunc).getResult(0); } mlir::Value fir::runtime::genGetUID(fir::FirOpBuilder &builder, @@ -165,7 +166,7 @@ mlir::Value fir::runtime::genGetUID(fir::FirOpBuilder &builder, auto runtimeFunc = fir::runtime::getRuntimeFunc(loc, builder); - return builder.create(loc, runtimeFunc).getResult(0); + return fir::CallOp::create(builder, loc, runtimeFunc).getResult(0); } mlir::Value fir::runtime::genMalloc(fir::FirOpBuilder &builder, @@ -186,7 +187,7 @@ void fir::runtime::genRandomInit(fir::FirOpBuilder &builder, mlir::Location loc, fir::runtime::getRuntimeFunc(loc, builder); llvm::SmallVector args = fir::runtime::createArguments( builder, loc, func.getFunctionType(), repeatable, imageDistinct); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void fir::runtime::genRandomNumber(fir::FirOpBuilder &builder, @@ -206,7 +207,7 @@ void fir::runtime::genRandomNumber(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, funcTy.getInput(2)); llvm::SmallVector args = fir::runtime::createArguments( builder, loc, funcTy, harvest, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void fir::runtime::genRandomSeed(fir::FirOpBuilder &builder, mlir::Location loc, @@ -223,7 +224,7 @@ void fir::runtime::genRandomSeed(fir::FirOpBuilder &builder, mlir::Location loc, if (staticArgCount == 0) { func = fir::runtime::getRuntimeFunc(loc, builder); - builder.create(loc, func); + fir::CallOp::create(builder, loc, func); return; } mlir::FunctionType funcTy; @@ -238,7 +239,7 @@ void fir::runtime::genRandomSeed(fir::FirOpBuilder &builder, mlir::Location loc, fir::factory::locationToLineNo(builder, loc, funcTy.getInput(4)); args = fir::runtime::createArguments(builder, loc, funcTy, size, put, get, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); return; } if (sizeIsPresent) { @@ -255,7 +256,7 @@ void fir::runtime::genRandomSeed(fir::FirOpBuilder &builder, mlir::Location loc, sourceLine = fir::factory::locationToLineNo(builder, loc, funcTy.getInput(2)); args = fir::runtime::createArguments(builder, loc, funcTy, argBox, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// generate rename runtime call @@ -273,14 +274,15 @@ void fir::runtime::genRename(fir::FirOpBuilder &builder, mlir::Location loc, llvm::SmallVector args = fir::runtime::createArguments(builder, loc, runtimeFuncTy, path1, path2, status, sourceFile, sourceLine); - builder.create(loc, runtimeFunc, args); + fir::CallOp::create(builder, loc, runtimeFunc, args); } /// generate runtime call to time intrinsic mlir::Value fir::runtime::genTime(fir::FirOpBuilder &builder, mlir::Location loc) { auto func = fir::runtime::getRuntimeFunc(loc, builder); - return builder.create(loc, func, std::nullopt).getResult(0); + return fir::CallOp::create(builder, loc, func, mlir::ValueRange{}) + .getResult(0); } /// generate runtime call to transfer intrinsic with no size argument @@ -296,7 +298,7 @@ void fir::runtime::genTransfer(fir::FirOpBuilder &builder, mlir::Location loc, fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); llvm::SmallVector args = fir::runtime::createArguments( builder, loc, fTy, resultBox, sourceBox, moldBox, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// generate runtime call to transfer intrinsic with size argument @@ -313,7 +315,7 @@ void fir::runtime::genTransferSize(fir::FirOpBuilder &builder, llvm::SmallVector args = fir::runtime::createArguments(builder, loc, fTy, resultBox, sourceBox, moldBox, sourceFile, sourceLine, size); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// generate system_clock runtime call/s @@ -330,11 +332,12 @@ void fir::runtime::genSystemClock(fir::FirOpBuilder &builder, mlir::dyn_cast(type)) { // Check for a disassociated pointer or an unallocated allocatable. assert(!isOptionalArg && "invalid optional argument"); - ifOp = builder.create(loc, builder.genIsNotNullAddr(loc, arg), - /*withElseRegion=*/false); + ifOp = fir::IfOp::create(builder, loc, builder.genIsNotNullAddr(loc, arg), + /*withElseRegion=*/false); } else if (isOptionalArg) { - ifOp = builder.create( - loc, builder.create(loc, builder.getI1Type(), arg), + ifOp = fir::IfOp::create( + builder, loc, + fir::IsPresentOp::create(builder, loc, builder.getI1Type(), arg), /*withElseRegion=*/false); } if (ifOp) @@ -346,11 +349,11 @@ void fir::runtime::genSystemClock(fir::FirOpBuilder &builder, integerKind = intType.getWidth() / 8; mlir::Value kind = builder.createIntegerConstant(loc, kindTy, integerKind); mlir::Value res = - builder.create(loc, func, mlir::ValueRange{kind}) + fir::CallOp::create(builder, loc, func, mlir::ValueRange{kind}) .getResult(0); mlir::Value castRes = builder.createConvert(loc, fir::dyn_cast_ptrEleTy(type), res); - builder.create(loc, castRes, arg); + fir::StoreOp::create(builder, loc, castRes, arg); if (ifOp) builder.setInsertionPointAfter(ifOp); }; @@ -371,24 +374,24 @@ void fir::runtime::genSignal(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value status) { assert(mlir::isa(number.getType())); mlir::Type int64 = builder.getIntegerType(64); - number = builder.create(loc, int64, number); + number = fir::ConvertOp::create(builder, loc, int64, number); mlir::Type handlerUnwrappedTy = fir::unwrapRefType(handler.getType()); if (mlir::isa_and_nonnull(handlerUnwrappedTy)) { // pass the integer as a function pointer like one would to signal(2) - handler = builder.create(loc, handler); + handler = fir::LoadOp::create(builder, loc, handler); mlir::Type fnPtrTy = fir::LLVMPointerType::get( mlir::FunctionType::get(handler.getContext(), {}, {})); - handler = builder.create(loc, fnPtrTy, handler); + handler = fir::ConvertOp::create(builder, loc, fnPtrTy, handler); } else { assert(mlir::isa(handler.getType())); - handler = builder.create(loc, handler); + handler = fir::BoxAddrOp::create(builder, loc, handler); } mlir::func::FuncOp func{ fir::runtime::getRuntimeFunc(loc, builder)}; mlir::Value stat = - builder.create(loc, func, mlir::ValueRange{number, handler}) + fir::CallOp::create(builder, loc, func, mlir::ValueRange{number, handler}) ->getResult(0); // return status code via status argument (if present) @@ -396,12 +399,12 @@ void fir::runtime::genSignal(fir::FirOpBuilder &builder, mlir::Location loc, assert(mlir::isa(fir::unwrapRefType(status.getType()))); // status might be dynamically optional, so test if it is present mlir::Value isPresent = - builder.create(loc, builder.getI1Type(), status); + IsPresentOp::create(builder, loc, builder.getI1Type(), status); builder.genIfOp(loc, /*results=*/{}, isPresent, /*withElseRegion=*/false) .genThen([&]() { - stat = builder.create( - loc, fir::unwrapRefType(status.getType()), stat); - builder.create(loc, stat, status); + stat = fir::ConvertOp::create( + builder, loc, fir::unwrapRefType(status.getType()), stat); + fir::StoreOp::create(builder, loc, stat, status); }) .end(); } @@ -410,10 +413,10 @@ void fir::runtime::genSignal(fir::FirOpBuilder &builder, mlir::Location loc, void fir::runtime::genSleep(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value seconds) { mlir::Type int64 = builder.getIntegerType(64); - seconds = builder.create(loc, int64, seconds); + seconds = fir::ConvertOp::create(builder, loc, int64, seconds); mlir::func::FuncOp func{ fir::runtime::getRuntimeFunc(loc, builder)}; - builder.create(loc, func, seconds); + fir::CallOp::create(builder, loc, func, seconds); } /// generate chdir runtime call @@ -423,5 +426,5 @@ mlir::Value fir::runtime::genChdir(fir::FirOpBuilder &builder, fir::runtime::getRuntimeFunc(loc, builder)}; llvm::SmallVector args = fir::runtime::createArguments(builder, loc, func.getFunctionType(), name); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } diff --git a/flang/lib/Optimizer/Builder/Runtime/Main.cpp b/flang/lib/Optimizer/Builder/Runtime/Main.cpp index 973744837d378..d35f687167b05 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Main.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Main.cpp @@ -62,17 +62,17 @@ void fir::runtime::genMain( llvm::SmallVector args(block->getArguments()); args.push_back(env); - builder.create(loc, startFn, args); + fir::CallOp::create(builder, loc, startFn, args); if (initCuda) { auto initFn = builder.createFunction( loc, RTNAME_STRING(CUFInit), mlir::FunctionType::get(context, {}, {})); - builder.create(loc, initFn); + fir::CallOp::create(builder, loc, initFn); } - builder.create(loc, qqMainFn); - builder.create(loc, stopFn); + fir::CallOp::create(builder, loc, qqMainFn); + fir::CallOp::create(builder, loc, stopFn); mlir::Value ret = builder.createIntegerConstant(loc, argcTy, 0); - builder.create(loc, ret); + mlir::func::ReturnOp::create(builder, loc, ret); } diff --git a/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp b/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp index 4ff7c86bb0a24..62d5e506cedf6 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp @@ -317,7 +317,7 @@ mlir::Value fir::runtime::genExponent(fir::FirOpBuilder &builder, llvm::SmallVector args = { builder.createConvert(loc, funcTy.getInput(0), x)}; - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } /// Generate call to Fraction intrinsic runtime routine. @@ -340,7 +340,7 @@ mlir::Value fir::runtime::genFraction(fir::FirOpBuilder &builder, llvm::SmallVector args = { builder.createConvert(loc, funcTy.getInput(0), x)}; - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } /// Generate call to Mod intrinsic runtime routine. @@ -370,7 +370,7 @@ mlir::Value fir::runtime::genMod(fir::FirOpBuilder &builder, mlir::Location loc, auto args = fir::runtime::createArguments(builder, loc, funcTy, a, p, sourceFile, sourceLine); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } /// Generate call to Modulo intrinsic runtime routine. @@ -403,7 +403,7 @@ mlir::Value fir::runtime::genModulo(fir::FirOpBuilder &builder, auto args = fir::runtime::createArguments(builder, loc, funcTy, a, p, sourceFile, sourceLine); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } /// Generate call to Nearest intrinsic or a "Next" intrinsic module procedure. @@ -427,7 +427,7 @@ mlir::Value fir::runtime::genNearest(fir::FirOpBuilder &builder, auto funcTy = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, funcTy, x, valueUp); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } /// Generate call to RRSpacing intrinsic runtime routine. @@ -451,7 +451,7 @@ mlir::Value fir::runtime::genRRSpacing(fir::FirOpBuilder &builder, llvm::SmallVector args = { builder.createConvert(loc, funcTy.getInput(0), x)}; - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } /// Generate call to ErfcScaled intrinsic runtime routine. @@ -475,7 +475,7 @@ mlir::Value fir::runtime::genErfcScaled(fir::FirOpBuilder &builder, llvm::SmallVector args = { builder.createConvert(loc, funcTy.getInput(0), x)}; - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } /// Generate call to Scale intrinsic runtime routine. @@ -499,7 +499,7 @@ mlir::Value fir::runtime::genScale(fir::FirOpBuilder &builder, auto funcTy = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, funcTy, x, i); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } /// Generate call to Selected_char_kind intrinsic runtime routine. @@ -519,7 +519,7 @@ mlir::Value fir::runtime::genSelectedCharKind(fir::FirOpBuilder &builder, auto args = fir::runtime::createArguments(builder, loc, fTy, sourceFile, sourceLine, name, length); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } /// Generate call to Selected_int_kind intrinsic runtime routine. @@ -540,7 +540,7 @@ mlir::Value fir::runtime::genSelectedIntKind(fir::FirOpBuilder &builder, auto args = fir::runtime::createArguments(builder, loc, fTy, sourceFile, sourceLine, x, xKind); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } /// Generate call to Selected_logical_kind intrinsic runtime routine. @@ -561,7 +561,7 @@ mlir::Value fir::runtime::genSelectedLogicalKind(fir::FirOpBuilder &builder, auto args = fir::runtime::createArguments(builder, loc, fTy, sourceFile, sourceLine, x, xKind); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } /// Generate call to Selected_real_kind intrinsic runtime routine. @@ -593,7 +593,7 @@ mlir::Value fir::runtime::genSelectedRealKind(fir::FirOpBuilder &builder, sourceLine, precision, pKind, range, rKind, radix, dKind); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } /// Generate call to Set_exponent intrinsic runtime routine. @@ -617,7 +617,7 @@ mlir::Value fir::runtime::genSetExponent(fir::FirOpBuilder &builder, auto funcTy = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, funcTy, x, i); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } /// Generate call to Spacing intrinsic runtime routine. @@ -649,6 +649,6 @@ mlir::Value fir::runtime::genSpacing(fir::FirOpBuilder &builder, llvm::SmallVector args = { builder.createConvert(loc, funcTy.getInput(0), x)}; - mlir::Value res = builder.create(loc, func, args).getResult(0); + mlir::Value res = fir::CallOp::create(builder, loc, func, args).getResult(0); return builder.createConvert(loc, fltTy, res); } diff --git a/flang/lib/Optimizer/Builder/Runtime/Pointer.cpp b/flang/lib/Optimizer/Builder/Runtime/Pointer.cpp index 160c6515a7a9d..c03ff5885d91e 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Pointer.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Pointer.cpp @@ -23,5 +23,5 @@ void fir::runtime::genPointerAssociateScalar(fir::FirOpBuilder &builder, mlir::FunctionType fTy{func.getFunctionType()}; llvm::SmallVector args{ fir::runtime::createArguments(builder, loc, fTy, desc, target)}; - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } diff --git a/flang/lib/Optimizer/Builder/Runtime/Ragged.cpp b/flang/lib/Optimizer/Builder/Runtime/Ragged.cpp index e5d0fb0fb27a9..e5cf96359ea38 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Ragged.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Ragged.cpp @@ -34,25 +34,25 @@ void fir::runtime::genRaggedArrayAllocate(mlir::Location loc, auto eleTy = fir::unwrapSequenceType(fir::unwrapRefType(header.getType())); auto ptrTy = builder.getRefType(mlir::cast(eleTy).getType(1)); - auto ptr = builder.create(loc, ptrTy, header, one); - auto heap = builder.create(loc, ptr); + auto ptr = fir::CoordinateOp::create(builder, loc, ptrTy, header, one); + auto heap = fir::LoadOp::create(builder, loc, ptr); auto cmp = builder.genIsNullAddr(loc, heap); builder.genIfThen(loc, cmp) .genThen([&]() { auto asHeadersVal = builder.createIntegerConstant(loc, i1Ty, asHeaders); auto rankVal = builder.createIntegerConstant(loc, i64Ty, rank); - auto buff = builder.create(loc, extentTy); + auto buff = fir::AllocMemOp::create(builder, loc, extentTy); // Convert all the extents to i64 and pack them in a buffer on the heap. for (auto i : llvm::enumerate(extents)) { auto offset = builder.createIntegerConstant(loc, i32Ty, i.index()); auto addr = - builder.create(loc, refTy, buff, offset); + fir::CoordinateOp::create(builder, loc, refTy, buff, offset); auto castVal = builder.createConvert(loc, i64Ty, i.value()); - builder.create(loc, castVal, addr); + fir::StoreOp::create(builder, loc, castVal, addr); } auto args = fir::runtime::createArguments( builder, loc, fTy, header, asHeadersVal, rankVal, eleSize, buff); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); }) .end(); } @@ -64,5 +64,5 @@ void fir::runtime::genRaggedArrayDeallocate(mlir::Location loc, loc, builder); auto fTy = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, fTy, header); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } diff --git a/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp b/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp index f778b963c59ca..157d4358329ce 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp @@ -1155,7 +1155,7 @@ mlir::Value genSpecial2Args(FN func, fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); auto args = fir::runtime::createArguments(builder, loc, fTy, maskBox, sourceFile, sourceLine, dim); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } /// Generate calls to reduction intrinsics such as All and Any. @@ -1171,7 +1171,7 @@ static void genReduction2Args(FN func, fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); auto args = fir::runtime::createArguments( builder, loc, fTy, resultBox, maskBox, dim, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Generate calls to reduction intrinsics such as Maxval and Minval. @@ -1189,7 +1189,7 @@ static void genReduction3Args(FN func, fir::FirOpBuilder &builder, auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox, dim, sourceFile, sourceLine, maskBox); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Generate calls to reduction intrinsics such as Maxloc and Minloc. @@ -1206,7 +1206,7 @@ static void genReduction4Args(FN func, fir::FirOpBuilder &builder, auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox, kind, sourceFile, sourceLine, maskBox, back); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Generate calls to reduction intrinsics such as Maxloc and Minloc. @@ -1223,7 +1223,7 @@ genReduction5Args(FN func, fir::FirOpBuilder &builder, mlir::Location loc, auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox, kind, dim, sourceFile, sourceLine, maskBox, back); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Generate call to `AllDim` runtime routine. @@ -1296,7 +1296,7 @@ void fir::runtime::genCountDim(fir::FirOpBuilder &builder, mlir::Location loc, fir::factory::locationToLineNo(builder, loc, fTy.getInput(5)); auto args = fir::runtime::createArguments( builder, loc, fTy, resultBox, maskBox, dim, kind, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Generate call to `Findloc` intrinsic runtime routine. This is the version @@ -1313,7 +1313,7 @@ void fir::runtime::genFindloc(fir::FirOpBuilder &builder, mlir::Location loc, auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox, valBox, kind, sourceFile, sourceLine, maskBox, back); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Generate call to `FindlocDim` intrinsic runtime routine. This is the version @@ -1331,7 +1331,7 @@ void fir::runtime::genFindlocDim(fir::FirOpBuilder &builder, mlir::Location loc, auto args = fir::runtime::createArguments( builder, loc, fTy, resultBox, arrayBox, valBox, kind, dim, sourceFile, sourceLine, maskBox, back); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Generate call to `Maxloc` intrinsic runtime routine. This is the version @@ -1392,7 +1392,7 @@ mlir::Value fir::runtime::genMaxval(fir::FirOpBuilder &builder, auto args = fir::runtime::createArguments( builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim, maskBox); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } /// Generate call to `MaxvalDim` intrinsic runtime routine. This is the version @@ -1417,7 +1417,7 @@ void fir::runtime::genMaxvalChar(fir::FirOpBuilder &builder, mlir::Location loc, fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); auto args = fir::runtime::createArguments( builder, loc, fTy, resultBox, arrayBox, sourceFile, sourceLine, maskBox); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Generate call to `Minloc` intrinsic runtime routine. This is the version @@ -1476,7 +1476,7 @@ void fir::runtime::genMinvalChar(fir::FirOpBuilder &builder, mlir::Location loc, fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); auto args = fir::runtime::createArguments( builder, loc, fTy, resultBox, arrayBox, sourceFile, sourceLine, maskBox); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Generate call to `Minval` intrinsic runtime routine. This is the version @@ -1504,7 +1504,7 @@ mlir::Value fir::runtime::genMinval(fir::FirOpBuilder &builder, auto args = fir::runtime::createArguments( builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim, maskBox); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } /// Generate call to `Norm2Dim` intrinsic runtime routine. This is the version @@ -1527,7 +1527,7 @@ void fir::runtime::genNorm2Dim(fir::FirOpBuilder &builder, mlir::Location loc, auto args = fir::runtime::createArguments( builder, loc, fTy, resultBox, arrayBox, dim, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Generate call to `Norm2` intrinsic runtime routine. This is the version @@ -1558,7 +1558,7 @@ mlir::Value fir::runtime::genNorm2(fir::FirOpBuilder &builder, auto args = fir::runtime::createArguments(builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } /// Generate call to `Parity` intrinsic runtime routine. This routine is @@ -1604,7 +1604,7 @@ mlir::Value fir::runtime::genProduct(fir::FirOpBuilder &builder, auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox, sourceFile, sourceLine, dim, maskBox); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); return resultBox; } @@ -1613,7 +1613,7 @@ mlir::Value fir::runtime::genProduct(fir::FirOpBuilder &builder, auto args = fir::runtime::createArguments( builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim, maskBox); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } /// Generate call to `DotProduct` intrinsic runtime routine. @@ -1645,7 +1645,7 @@ mlir::Value fir::runtime::genDotProduct(fir::FirOpBuilder &builder, auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, vectorABox, vectorBBox, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); return resultBox; } @@ -1653,7 +1653,7 @@ mlir::Value fir::runtime::genDotProduct(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); auto args = fir::runtime::createArguments(builder, loc, fTy, vectorABox, vectorBBox, sourceFile, sourceLine); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } /// Generate call to `SumDim` intrinsic runtime routine. This is the version /// that handles any rank array with the dim argument specified. @@ -1688,7 +1688,7 @@ mlir::Value fir::runtime::genSum(fir::FirOpBuilder &builder, mlir::Location loc, auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox, sourceFile, sourceLine, dim, maskBox); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); return resultBox; } @@ -1697,7 +1697,7 @@ mlir::Value fir::runtime::genSum(fir::FirOpBuilder &builder, mlir::Location loc, auto args = fir::runtime::createArguments( builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim, maskBox); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } // The IAll, IAny and IParity intrinsics have essentially the same @@ -1733,7 +1733,7 @@ mlir::Value fir::runtime::genSum(fir::FirOpBuilder &builder, mlir::Location loc, auto args = fir::runtime::createArguments( \ builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim, maskBox); \ \ - return builder.create(loc, func, args).getResult(0); \ + return fir::CallOp::create(builder, loc, func, args).getResult(0); \ } /// Generate call to `IAllDim` intrinsic runtime routine. This is the version @@ -1819,11 +1819,12 @@ void fir::runtime::genReduce(fir::FirOpBuilder &builder, mlir::Location loc, auto sourceFile = fir::factory::locationToFilename(builder, loc); auto sourceLine = fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); - auto opAddr = builder.create(loc, fTy.getInput(2), operation); + auto opAddr = + fir::BoxAddrOp::create(builder, loc, fTy.getInput(2), operation); auto args = fir::runtime::createArguments( builder, loc, fTy, resultBox, arrayBox, opAddr, sourceFile, sourceLine, dim, maskBox, identity, ordered); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Generate call to `Reduce` intrinsic runtime routine. This is the version @@ -1864,11 +1865,12 @@ mlir::Value fir::runtime::genReduce(fir::FirOpBuilder &builder, auto sourceFile = fir::factory::locationToFilename(builder, loc); auto sourceLine = fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); - auto opAddr = builder.create(loc, fTy.getInput(1), operation); + auto opAddr = + fir::BoxAddrOp::create(builder, loc, fTy.getInput(1), operation); auto args = fir::runtime::createArguments(builder, loc, fTy, arrayBox, opAddr, sourceFile, sourceLine, dim, maskBox, identity, ordered); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } void fir::runtime::genReduceDim(fir::FirOpBuilder &builder, mlir::Location loc, @@ -1912,9 +1914,10 @@ void fir::runtime::genReduceDim(fir::FirOpBuilder &builder, mlir::Location loc, auto sourceLine = fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); - auto opAddr = builder.create(loc, fTy.getInput(2), operation); + auto opAddr = + fir::BoxAddrOp::create(builder, loc, fTy.getInput(2), operation); auto args = fir::runtime::createArguments( builder, loc, fTy, resultBox, arrayBox, opAddr, sourceFile, sourceLine, dim, maskBox, identity, ordered); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } diff --git a/flang/lib/Optimizer/Builder/Runtime/Stop.cpp b/flang/lib/Optimizer/Builder/Runtime/Stop.cpp index 411181cc6dd1c..5629371947641 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Stop.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Stop.cpp @@ -19,13 +19,13 @@ void fir::runtime::genExit(fir::FirOpBuilder &builder, mlir::Location loc, auto exitFunc = fir::runtime::getRuntimeFunc(loc, builder); llvm::SmallVector args = fir::runtime::createArguments( builder, loc, exitFunc.getFunctionType(), status); - builder.create(loc, exitFunc, args); + fir::CallOp::create(builder, loc, exitFunc, args); } void fir::runtime::genAbort(fir::FirOpBuilder &builder, mlir::Location loc) { mlir::func::FuncOp abortFunc = fir::runtime::getRuntimeFunc(loc, builder); - builder.create(loc, abortFunc, std::nullopt); + fir::CallOp::create(builder, loc, abortFunc, mlir::ValueRange{}); } void fir::runtime::genReportFatalUserError(fir::FirOpBuilder &builder, @@ -41,5 +41,5 @@ void fir::runtime::genReportFatalUserError(fir::FirOpBuilder &builder, mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); llvm::SmallVector args = fir::runtime::createArguments( builder, loc, funcTy, msgVal, sourceFile, sourceLine); - builder.create(loc, crashFunc, args); + fir::CallOp::create(builder, loc, crashFunc, args); } diff --git a/flang/lib/Optimizer/Builder/Runtime/Support.cpp b/flang/lib/Optimizer/Builder/Runtime/Support.cpp index b5e9ddb87c7c4..d0d48ad718da4 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Support.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Support.cpp @@ -42,7 +42,7 @@ void fir::runtime::genCopyAndUpdateDescriptor(fir::FirOpBuilder &builder, func.setArgAttr(0, noCapture, unitAttr); func.setArgAttr(1, noCapture, unitAttr); } - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } mlir::Value fir::runtime::genIsAssumedSize(fir::FirOpBuilder &builder, @@ -52,5 +52,5 @@ mlir::Value fir::runtime::genIsAssumedSize(fir::FirOpBuilder &builder, fir::runtime::getRuntimeFunc(loc, builder); auto fTy = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, fTy, box); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } diff --git a/flang/lib/Optimizer/Builder/Runtime/TemporaryStack.cpp b/flang/lib/Optimizer/Builder/Runtime/TemporaryStack.cpp index 732152c823a06..effd712079753 100644 --- a/flang/lib/Optimizer/Builder/Runtime/TemporaryStack.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/TemporaryStack.cpp @@ -23,7 +23,7 @@ mlir::Value fir::runtime::genCreateValueStack(mlir::Location loc, fir::factory::locationToLineNo(builder, loc, funcType.getInput(1)); auto args = fir::runtime::createArguments(builder, loc, funcType, sourceFile, sourceLine); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } void fir::runtime::genPushValue(mlir::Location loc, fir::FirOpBuilder &builder, @@ -33,7 +33,7 @@ void fir::runtime::genPushValue(mlir::Location loc, fir::FirOpBuilder &builder, mlir::FunctionType funcType = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, funcType, opaquePtr, boxValue); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void fir::runtime::genValueAt(mlir::Location loc, fir::FirOpBuilder &builder, @@ -44,7 +44,7 @@ void fir::runtime::genValueAt(mlir::Location loc, fir::FirOpBuilder &builder, mlir::FunctionType funcType = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, funcType, opaquePtr, i, retValueBox); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void fir::runtime::genDestroyValueStack(mlir::Location loc, @@ -54,7 +54,7 @@ void fir::runtime::genDestroyValueStack(mlir::Location loc, fir::runtime::getRuntimeFunc(loc, builder); mlir::FunctionType funcType = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, funcType, opaquePtr); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } mlir::Value fir::runtime::genCreateDescriptorStack(mlir::Location loc, @@ -68,7 +68,7 @@ mlir::Value fir::runtime::genCreateDescriptorStack(mlir::Location loc, fir::factory::locationToLineNo(builder, loc, funcType.getInput(1)); auto args = fir::runtime::createArguments(builder, loc, funcType, sourceFile, sourceLine); - return builder.create(loc, func, args).getResult(0); + return fir::CallOp::create(builder, loc, func, args).getResult(0); } void fir::runtime::genPushDescriptor(mlir::Location loc, @@ -80,7 +80,7 @@ void fir::runtime::genPushDescriptor(mlir::Location loc, mlir::FunctionType funcType = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, funcType, opaquePtr, boxDescriptor); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void fir::runtime::genDescriptorAt(mlir::Location loc, @@ -92,7 +92,7 @@ void fir::runtime::genDescriptorAt(mlir::Location loc, mlir::FunctionType funcType = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, funcType, opaquePtr, i, retDescriptorBox); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } void fir::runtime::genDestroyDescriptorStack(mlir::Location loc, @@ -103,5 +103,5 @@ void fir::runtime::genDestroyDescriptorStack(mlir::Location loc, builder); mlir::FunctionType funcType = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, funcType, opaquePtr); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } diff --git a/flang/lib/Optimizer/Builder/Runtime/Transformational.cpp b/flang/lib/Optimizer/Builder/Runtime/Transformational.cpp index 47744b0facb53..6251def5cfb17 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Transformational.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Transformational.cpp @@ -170,7 +170,7 @@ void fir::runtime::genBesselJn(fir::FirOpBuilder &builder, mlir::Location loc, auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, n1, n2, x, bn2, bn2_1, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Generate call to `BesselJn` intrinsic. This is used when `x == 0.0`. @@ -196,7 +196,7 @@ void fir::runtime::genBesselJnX0(fir::FirOpBuilder &builder, mlir::Location loc, fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, n1, n2, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Generate call to `BesselYn` intrinsic. @@ -225,7 +225,7 @@ void fir::runtime::genBesselYn(fir::FirOpBuilder &builder, mlir::Location loc, auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, n1, n2, x, bn1, bn1_1, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Generate call to `BesselYn` intrinsic. This is used when `x == 0.0`. @@ -251,7 +251,7 @@ void fir::runtime::genBesselYnX0(fir::FirOpBuilder &builder, mlir::Location loc, fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, n1, n2, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Generate call to Cshift intrinsic @@ -266,7 +266,7 @@ void fir::runtime::genCshift(fir::FirOpBuilder &builder, mlir::Location loc, auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox, shiftBox, dimBox, sourceFile, sourceLine); - builder.create(loc, cshiftFunc, args); + fir::CallOp::create(builder, loc, cshiftFunc, args); } /// Generate call to the vector version of the Cshift intrinsic @@ -282,7 +282,7 @@ void fir::runtime::genCshiftVector(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); auto args = fir::runtime::createArguments( builder, loc, fTy, resultBox, arrayBox, shiftBox, sourceFile, sourceLine); - builder.create(loc, cshiftFunc, args); + fir::CallOp::create(builder, loc, cshiftFunc, args); } /// Generate call to Eoshift intrinsic @@ -299,7 +299,7 @@ void fir::runtime::genEoshift(fir::FirOpBuilder &builder, mlir::Location loc, auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox, shiftBox, boundBox, dimBox, sourceFile, sourceLine); - builder.create(loc, eoshiftFunc, args); + fir::CallOp::create(builder, loc, eoshiftFunc, args); } /// Generate call to the vector version of the Eoshift intrinsic @@ -318,7 +318,7 @@ void fir::runtime::genEoshiftVector(fir::FirOpBuilder &builder, auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox, shiftBox, boundBox, sourceFile, sourceLine); - builder.create(loc, eoshiftFunc, args); + fir::CallOp::create(builder, loc, eoshiftFunc, args); } /// Define ForcedMatmul models. @@ -388,7 +388,7 @@ void fir::runtime::genMatmul(fir::FirOpBuilder &builder, mlir::Location loc, auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, matrixABox, matrixBBox, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Define ForcedMatmulTranspose models. @@ -440,7 +440,7 @@ void fir::runtime::genMatmulTranspose(fir::FirOpBuilder &builder, auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, matrixABox, matrixBBox, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Generate call to Pack intrinsic runtime routine. @@ -455,7 +455,7 @@ void fir::runtime::genPack(fir::FirOpBuilder &builder, mlir::Location loc, auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox, maskBox, vectorBox, sourceFile, sourceLine); - builder.create(loc, packFunc, args); + fir::CallOp::create(builder, loc, packFunc, args); } /// Generate call to Reshape intrinsic runtime routine. @@ -471,7 +471,7 @@ void fir::runtime::genReshape(fir::FirOpBuilder &builder, mlir::Location loc, auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, sourceBox, shapeBox, padBox, orderBox, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Generate call to ShallowCopy[Direct] runtime routine. @@ -491,7 +491,7 @@ void fir::runtime::genShallowCopy(fir::FirOpBuilder &builder, fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox, sourceFile, sourceLine); - builder.create(loc, packFunc, args); + fir::CallOp::create(builder, loc, packFunc, args); } /// Generate call to Spread intrinsic runtime routine. @@ -506,7 +506,7 @@ void fir::runtime::genSpread(fir::FirOpBuilder &builder, mlir::Location loc, auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, sourceBox, dim, ncopies, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Generate call to Transpose intrinsic runtime routine. @@ -519,7 +519,7 @@ void fir::runtime::genTranspose(fir::FirOpBuilder &builder, mlir::Location loc, fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, sourceBox, sourceFile, sourceLine); - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } /// Generate call to Unpack intrinsic runtime routine. @@ -534,5 +534,5 @@ void fir::runtime::genUnpack(fir::FirOpBuilder &builder, mlir::Location loc, auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, vectorBox, maskBox, fieldBox, sourceFile, sourceLine); - builder.create(loc, unpackFunc, args); + fir::CallOp::create(builder, loc, unpackFunc, args); } diff --git a/flang/lib/Optimizer/Builder/TemporaryStorage.cpp b/flang/lib/Optimizer/Builder/TemporaryStorage.cpp index 9d2e9837a3df8..4c648df18b328 100644 --- a/flang/lib/Optimizer/Builder/TemporaryStorage.cpp +++ b/flang/lib/Optimizer/Builder/TemporaryStorage.cpp @@ -28,7 +28,7 @@ fir::factory::Counter::Counter(mlir::Location loc, fir::FirOpBuilder &builder, one = builder.createIntegerConstant(loc, type, 1); if (canCountThroughLoops) { index = builder.createTemporary(loc, type); - builder.create(loc, initialValue, index); + fir::StoreOp::create(builder, loc, initialValue, index); } else { index = initialValue; } @@ -38,21 +38,21 @@ mlir::Value fir::factory::Counter::getAndIncrementIndex(mlir::Location loc, fir::FirOpBuilder &builder) { if (canCountThroughLoops) { - mlir::Value indexValue = builder.create(loc, index); + mlir::Value indexValue = fir::LoadOp::create(builder, loc, index); mlir::Value newValue = - builder.create(loc, indexValue, one); - builder.create(loc, newValue, index); + mlir::arith::AddIOp::create(builder, loc, indexValue, one); + fir::StoreOp::create(builder, loc, newValue, index); return indexValue; } mlir::Value indexValue = index; - index = builder.create(loc, indexValue, one); + index = mlir::arith::AddIOp::create(builder, loc, indexValue, one); return indexValue; } void fir::factory::Counter::reset(mlir::Location loc, fir::FirOpBuilder &builder) { if (canCountThroughLoops) - builder.create(loc, initialValue, index); + fir::StoreOp::create(builder, loc, initialValue, index); else index = initialValue; } @@ -103,7 +103,7 @@ void fir::factory::HomogeneousScalarStack::pushValue(mlir::Location loc, // below should not get hit but is added as a remainder/safety. if (!entity.hasIntrinsicType()) TODO(loc, "creating inlined temporary stack for derived types"); - builder.create(loc, value, tempElement); + hlfir::AssignOp::create(builder, loc, value, tempElement); } void fir::factory::HomogeneousScalarStack::resetFetchPosition( @@ -125,14 +125,14 @@ void fir::factory::HomogeneousScalarStack::destroy(mlir::Location loc, if (allocateOnHeap) { auto declare = temp.getDefiningOp(); assert(declare && "temp must have been declared"); - builder.create(loc, declare.getMemref()); + fir::FreeMemOp::create(builder, loc, declare.getMemref()); } } hlfir::Entity fir::factory::HomogeneousScalarStack::moveStackAsArrayExpr( mlir::Location loc, fir::FirOpBuilder &builder) { mlir::Value mustFree = builder.createBool(loc, allocateOnHeap); - auto hlfirExpr = builder.create(loc, temp, mustFree); + auto hlfirExpr = hlfir::AsExprOp::create(builder, loc, temp, mustFree); return hlfir::Entity{hlfirExpr}; } @@ -147,14 +147,14 @@ fir::factory::SimpleCopy::SimpleCopy(mlir::Location loc, // Use hlfir.as_expr and hlfir.associate to create a copy and leave // bufferization deals with how best to make the copy. if (source.isVariable()) - source = hlfir::Entity{builder.create(loc, source)}; + source = hlfir::Entity{hlfir::AsExprOp::create(builder, loc, source)}; copy = hlfir::genAssociateExpr(loc, builder, source, source.getFortranElementType(), tempName); } void fir::factory::SimpleCopy::destroy(mlir::Location loc, fir::FirOpBuilder &builder) { - builder.create(loc, copy); + hlfir::EndAssociateOp::create(builder, loc, copy); } //===----------------------------------------------------------------------===// @@ -279,7 +279,7 @@ mlir::Value fir::factory::AnyVariableStack::fetch(mlir::Location loc, mlir::Value indexValue = counter.getAndIncrementIndex(loc, builder); fir::runtime::genDescriptorAt(loc, builder, opaquePtr, indexValue, retValueBox); - hlfir::Entity retBox{builder.create(loc, retValueBox)}; + hlfir::Entity retBox{fir::LoadOp::create(builder, loc, retValueBox)}; // The runtime always tracks variable as address, but the form of the variable // that was saved may be different (raw address, fir.boxchar), ensure // the returned variable has the same form of the one that was saved. @@ -326,7 +326,7 @@ void fir::factory::AnyVectorSubscriptStack::pushShape( hlfir::getFortranElementOrSequenceType(*boxType)); mlir::Value null = builder.createNullConstant(loc, refType); mlir::Value descriptor = - builder.create(loc, *boxType, null, shape); + fir::EmboxOp::create(builder, loc, *boxType, null, shape); shapeTemp->pushValue(loc, builder, descriptor); return; } @@ -372,7 +372,7 @@ void fir::factory::AnyAddressStack::pushValue(mlir::Location loc, mlir::Value cast = variable; if (auto boxProcType = llvm::dyn_cast(variable.getType())) { cast = - builder.create(loc, boxProcType.getEleTy(), variable); + fir::BoxAddrOp::create(builder, loc, boxProcType.getEleTy(), variable); } cast = builder.createConvert(loc, builder.getIntPtrType(), cast); static_cast(this)->pushValue(loc, builder, cast); @@ -383,7 +383,7 @@ mlir::Value fir::factory::AnyAddressStack::fetch(mlir::Location loc, mlir::Value addr = static_cast(this)->fetch(loc, builder); if (auto boxProcType = llvm::dyn_cast(addressType)) { mlir::Value cast = builder.createConvert(loc, boxProcType.getEleTy(), addr); - return builder.create(loc, boxProcType, cast); + return fir::EmboxProcOp::create(builder, loc, boxProcType, cast); } return builder.createConvert(loc, addressType, addr); } diff --git a/flang/lib/Optimizer/CodeGen/CMakeLists.txt b/flang/lib/Optimizer/CodeGen/CMakeLists.txt index 980307db315d9..d5ea3c7a8e282 100644 --- a/flang/lib/Optimizer/CodeGen/CMakeLists.txt +++ b/flang/lib/Optimizer/CodeGen/CMakeLists.txt @@ -34,8 +34,10 @@ add_flang_library(FIRCodeGen MLIR_LIBS MLIRComplexToLLVM + MLIRComplexToROCDLLibraryCalls MLIRComplexToStandard MLIRGPUDialect + MLIRIndexToLLVM MLIRMathToFuncs MLIRMathToLLVM MLIRMathToLibm diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index ecc04a6c9a2be..609ba27bc212b 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -33,9 +33,11 @@ #include "mlir/Conversion/ArithCommon/AttrToLLVMConverter.h" #include "mlir/Conversion/ArithToLLVM/ArithToLLVM.h" #include "mlir/Conversion/ComplexToLLVM/ComplexToLLVM.h" +#include "mlir/Conversion/ComplexToROCDLLibraryCalls/ComplexToROCDLLibraryCalls.h" #include "mlir/Conversion/ComplexToStandard/ComplexToStandard.h" #include "mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h" #include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h" +#include "mlir/Conversion/IndexToLLVM/IndexToLLVM.h" #include "mlir/Conversion/LLVMCommon/Pattern.h" #include "mlir/Conversion/MathToFuncs/MathToFuncs.h" #include "mlir/Conversion/MathToLLVM/MathToLLVM.h" @@ -1122,6 +1124,16 @@ struct AllocMemOpConversion : public fir::FIROpConversion { for (mlir::Value opnd : adaptor.getOperands()) size = rewriter.create( loc, ity, size, integerCast(loc, rewriter, ity, opnd)); + + // As the return value of malloc(0) is implementation defined, allocate one + // byte to ensure the allocation status being true. This behavior aligns to + // what the runtime has. + mlir::Value zero = genConstantIndex(loc, ity, rewriter, 0); + mlir::Value one = genConstantIndex(loc, ity, rewriter, 1); + mlir::Value cmp = rewriter.create( + loc, mlir::LLVM::ICmpPredicate::sgt, size, zero); + size = rewriter.create(loc, cmp, size, one); + auto mallocTyWidth = lowerTy().getIndexTypeBitwidth(); auto mallocTy = mlir::IntegerType::get(rewriter.getContext(), mallocTyWidth); @@ -4145,22 +4157,24 @@ class FIRToLLVMLowering // conversions that affect the ModuleOp, e.g. create new // function operations in it. We have to run such conversions // as passes here. - mlir::OpPassManager mathConvertionPM("builtin.module"); + mlir::OpPassManager mathConversionPM("builtin.module"); bool isAMDGCN = fir::getTargetTriple(mod).isAMDGCN(); // If compiling for AMD target some math operations must be lowered to AMD // GPU library calls, the rest can be converted to LLVM intrinsics, which // is handled in the mathToLLVM conversion. The lowering to libm calls is // not needed since all math operations are handled this way. - if (isAMDGCN) - mathConvertionPM.addPass(mlir::createConvertMathToROCDL()); + if (isAMDGCN) { + mathConversionPM.addPass(mlir::createConvertMathToROCDL()); + mathConversionPM.addPass(mlir::createConvertComplexToROCDLLibraryCalls()); + } // Convert math::FPowI operations to inline implementation // only if the exponent's width is greater than 32, otherwise, // it will be lowered to LLVM intrinsic operation by a later conversion. mlir::ConvertMathToFuncsOptions mathToFuncsOptions{}; mathToFuncsOptions.minWidthOfFPowIExponent = 33; - mathConvertionPM.addPass( + mathConversionPM.addPass( mlir::createConvertMathToFuncs(mathToFuncsOptions)); mlir::ConvertComplexToStandardPassOptions complexToStandardOptions{}; @@ -4173,15 +4187,15 @@ class FIRToLLVMLowering complexToStandardOptions.complexRange = mlir::complex::ComplexRangeFlags::improved; } - mathConvertionPM.addPass( + mathConversionPM.addPass( mlir::createConvertComplexToStandardPass(complexToStandardOptions)); // Convert Math dialect operations into LLVM dialect operations. // There is no way to prefer MathToLLVM patterns over MathToLibm // patterns (applied below), so we have to run MathToLLVM conversion here. - mathConvertionPM.addNestedPass( + mathConversionPM.addNestedPass( mlir::createConvertMathToLLVMPass()); - if (mlir::failed(runPipeline(mathConvertionPM, mod))) + if (mlir::failed(runPipeline(mathConversionPM, mod))) return signalPassFailure(); std::optional dl = @@ -4211,6 +4225,7 @@ class FIRToLLVMLowering if (!isAMDGCN) mlir::populateMathToLibmConversionPatterns(pattern); mlir::populateComplexToLLVMConversionPatterns(typeConverter, pattern); + mlir::index::populateIndexToLLVMConversionPatterns(typeConverter, pattern); mlir::populateVectorToLLVMConversionPatterns(typeConverter, pattern); // Flang specific overloads for OpenMP operations, to allow for special diff --git a/flang/lib/Optimizer/CodeGen/LowerRepackArrays.cpp b/flang/lib/Optimizer/CodeGen/LowerRepackArrays.cpp index e34771c67b0c3..d2cf85bedd54c 100644 --- a/flang/lib/Optimizer/CodeGen/LowerRepackArrays.cpp +++ b/flang/lib/Optimizer/CodeGen/LowerRepackArrays.cpp @@ -63,13 +63,14 @@ class PackArrayConversion : public mlir::OpRewritePattern { static constexpr llvm::StringRef bufferName = ".repacked"; // Return value of fir::BaseBoxType that represents a temporary - // array created for the original box with given extents and - // type parameters. The new box has the default lower bounds. - // If useStack is true, then the temporary will be allocated + // array created for the original box with given lbounds/extents and + // type parameters. The new box has the same shape as the original + // array. If useStack is true, then the temporary will be allocated // in stack memory (when possible). static mlir::Value allocateTempBuffer(fir::FirOpBuilder &builder, mlir::Location loc, bool useStack, mlir::Value origBox, + llvm::ArrayRef lbounds, llvm::ArrayRef extents, llvm::ArrayRef typeParams); @@ -99,7 +100,9 @@ class UnpackArrayConversion // the presence of the stack attribute does not automatically // mean that the allocation is actually done in stack memory. // For example, we always do the heap allocation for polymorphic -// types using Fortran runtime. +// types using Fortran runtime. Currently, we allocate all +// repack temporaries of derived types as polymorphic, +// so that we can preserve the dynamic type of the original. // Adding the polymorpic mold to fir.alloca and then using // Fortran runtime to compute the allocation size could probably // resolve this limitation. @@ -170,7 +173,8 @@ PackArrayConversion::matchAndRewrite(fir::PackArrayOp op, mlir::Value PackArrayConversion::allocateTempBuffer( fir::FirOpBuilder &builder, mlir::Location loc, bool useStack, - mlir::Value origBox, llvm::ArrayRef extents, + mlir::Value origBox, llvm::ArrayRef lbounds, + llvm::ArrayRef extents, llvm::ArrayRef typeParams) { auto tempType = mlir::cast( fir::extractSequenceType(origBox.getType())); @@ -191,16 +195,35 @@ mlir::Value PackArrayConversion::allocateTempBuffer( assert(!isHeapAllocation && "temp must have been allocated on the stack"); mlir::Type ptrType = base.getType(); - if (llvm::isa(ptrType)) - return base; + if (auto tempBoxType = mlir::dyn_cast(ptrType)) { + // We need to reset the CFI_attribute_allocatable before + // returning the temporary box to avoid any mishandling + // of the temporary box in Fortran runtime. + base = builder.create(loc, fir::boxMemRefType(tempBoxType), + base); + ptrType = base.getType(); + } - mlir::Type tempBoxType = fir::BoxType::get(mlir::isa(ptrType) - ? ptrType - : fir::unwrapRefType(ptrType)); + // Create the temporary using dynamic type of the original, + // if it is polymorphic, or it has a derived type with SEQUENCE + // or BIND attribute (such dummy arguments may have their dynamic + // type not exactly matching their static type). + // Note that for the latter case, the allocation can still be done + // without the mold, because the dynamic and static types + // must be storage compatible. + bool useDynamicType = fir::isBoxedRecordType(origBox.getType()) || + fir::isPolymorphicType(origBox.getType()); + mlir::Type tempBoxType = + fir::wrapInClassOrBoxType(fir::unwrapRefType(ptrType), + /*isPolymorphic=*/useDynamicType); + // Use the shape with proper lower bounds for the final box. + shape = builder.genShape(loc, lbounds, extents); mlir::Value newBox = builder.createBox(loc, tempBoxType, base, shape, /*slice=*/nullptr, - typeParams, /*tdesc=*/nullptr); - return newBox; + typeParams, useDynamicType ? origBox : nullptr); + // The new box might be !fir.class, while the original might be + // !fir.box - we have to add a conversion. + return builder.createConvert(loc, origBox.getType(), newBox); } mlir::FailureOr @@ -280,16 +303,11 @@ PackArrayConversion::genRepackedBox(fir::FirOpBuilder &builder, << op.getOperation() << '\n'; } - mlir::Value tempBox = - allocateTempBuffer(builder, loc, op.getStack(), box, extents, typeParams); + mlir::Value tempBox = allocateTempBuffer(builder, loc, op.getStack(), box, + lbounds, extents, typeParams); if (!op.getNoCopy()) fir::runtime::genShallowCopy(builder, loc, tempBox, box, /*resultIsAllocated=*/true); - - // Set lower bounds after the original box. - mlir::Value shift = builder.genShift(loc, lbounds); - tempBox = builder.create(loc, boxType, tempBox, shift, - /*slice=*/nullptr); builder.create(loc, tempBox); return ifOp.getResult(0); diff --git a/flang/lib/Optimizer/CodeGen/Target.cpp b/flang/lib/Optimizer/CodeGen/Target.cpp index 7dbf21ce0c125..b60a72e4340b9 100644 --- a/flang/lib/Optimizer/CodeGen/Target.cpp +++ b/flang/lib/Optimizer/CodeGen/Target.cpp @@ -1443,14 +1443,35 @@ struct TargetAMDGPU : public GenericTarget { CodeGenSpecifics::Marshalling complexArgumentType(mlir::Location loc, mlir::Type eleTy) const override { CodeGenSpecifics::Marshalling marshal; - TODO(loc, "handle complex argument types"); + const auto *sem = &floatToSemantics(kindMap, eleTy); + if (sem == &llvm::APFloat::IEEEsingle()) { + // Lower COMPLEX(KIND=4) as an array of two element values. + marshal.emplace_back(fir::SequenceType::get({2}, eleTy), AT{}); + } else if (sem == &llvm::APFloat::IEEEdouble()) { + // Pass COMPLEX(KIND=8) as two separate arguments. + marshal.emplace_back(eleTy, AT{}); + marshal.emplace_back(eleTy, AT{}); + } else { + typeTodo(sem, loc, "argument"); + } return marshal; } CodeGenSpecifics::Marshalling complexReturnType(mlir::Location loc, mlir::Type eleTy) const override { CodeGenSpecifics::Marshalling marshal; - TODO(loc, "handle complex return types"); + const auto *sem = &floatToSemantics(kindMap, eleTy); + if (sem == &llvm::APFloat::IEEEsingle()) { + // Return COMPLEX(KIND=4) as an array of two elements. + marshal.emplace_back(fir::SequenceType::get({2}, eleTy), AT{}); + } else if (sem == &llvm::APFloat::IEEEdouble()) { + // Return COMPLEX(KIND=8) via an aggregate with two fields. + marshal.emplace_back(mlir::TupleType::get(eleTy.getContext(), + mlir::TypeRange{eleTy, eleTy}), + AT{}); + } else { + typeTodo(sem, loc, "return"); + } return marshal; } }; diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp index b6bf2753b80ce..cf20d84cbbcdb 100644 --- a/flang/lib/Optimizer/Dialect/FIROps.cpp +++ b/flang/lib/Optimizer/Dialect/FIROps.cpp @@ -4448,7 +4448,7 @@ llvm::LogicalResult fir::UnboxProcOp::verify() { void fir::IfOp::build(mlir::OpBuilder &builder, mlir::OperationState &result, mlir::Value cond, bool withElseRegion) { - build(builder, result, std::nullopt, cond, withElseRegion); + build(builder, result, {}, cond, withElseRegion); } void fir::IfOp::build(mlir::OpBuilder &builder, mlir::OperationState &result, diff --git a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp index 58f2b57712974..00ca6731c035b 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp @@ -296,7 +296,7 @@ struct SetLengthOpConversion llvm::StringRef tmpName{".tmp"}; llvm::SmallVector lenParams{adaptor.getLength()}; auto alloca = builder.createTemporary(loc, charType, tmpName, - /*shape=*/std::nullopt, lenParams); + /*shape=*/{}, lenParams); auto declareOp = builder.create( loc, alloca, tmpName, /*shape=*/mlir::Value{}, lenParams, /*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{}); diff --git a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp index 03cc92e975b19..c5cf01ed98357 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp @@ -405,7 +405,7 @@ void OrderedAssignmentRewriter::pre(hlfir::ForallMaskOp forallMaskOp) { mlir::Location loc = forallMaskOp.getLoc(); mlir::Value mask = generateYieldedScalarValue(forallMaskOp.getMaskRegion(), builder.getI1Type()); - auto ifOp = builder.create(loc, std::nullopt, mask, false); + auto ifOp = builder.create(loc, mlir::TypeRange{}, mask, false); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); constructStack.push_back(ifOp); } @@ -530,7 +530,7 @@ void OrderedAssignmentRewriter::generateMaskIfOp(mlir::Value cdt) { mlir::Location loc = cdt.getLoc(); cdt = hlfir::loadTrivialScalar(loc, builder, hlfir::Entity{cdt}); cdt = builder.createConvert(loc, builder.getI1Type(), cdt); - auto ifOp = builder.create(cdt.getLoc(), std::nullopt, cdt, + auto ifOp = builder.create(cdt.getLoc(), mlir::TypeRange{}, cdt, /*withElseRegion=*/false); constructStack.push_back(ifOp.getOperation()); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); diff --git a/flang/lib/Optimizer/Transforms/AbstractResult.cpp b/flang/lib/Optimizer/Transforms/AbstractResult.cpp index 59e2eeb76c715..391cfe3ceb9a2 100644 --- a/flang/lib/Optimizer/Transforms/AbstractResult.cpp +++ b/flang/lib/Optimizer/Transforms/AbstractResult.cpp @@ -137,9 +137,9 @@ class CallConversion : public mlir::OpRewritePattern { auto buffer = saveResult.getMemref(); mlir::Value arg = buffer; if (mustEmboxResult(result.getType(), shouldBoxResult)) - arg = rewriter.create( - loc, argType, buffer, saveResult.getShape(), /*slice*/ mlir::Value{}, - saveResult.getTypeparams()); + arg = fir::EmboxOp::create(rewriter, loc, argType, buffer, + saveResult.getShape(), /*slice*/ mlir::Value{}, + saveResult.getTypeparams()); llvm::SmallVector newResultTypes; bool isResultBuiltinCPtr = fir::isa_builtin_cptr_type(result.getType()); @@ -155,8 +155,8 @@ class CallConversion : public mlir::OpRewritePattern { if (!isResultBuiltinCPtr) newOperands.emplace_back(arg); newOperands.append(op.getOperands().begin(), op.getOperands().end()); - newOp = rewriter.create(loc, *op.getCallee(), - newResultTypes, newOperands); + newOp = fir::CallOp::create(rewriter, loc, *op.getCallee(), + newResultTypes, newOperands); } else { // Indirect calls. llvm::SmallVector newInputTypes; @@ -169,13 +169,13 @@ class CallConversion : public mlir::OpRewritePattern { llvm::SmallVector newOperands; newOperands.push_back( - rewriter.create(loc, newFuncTy, op.getOperand(0))); + fir::ConvertOp::create(rewriter, loc, newFuncTy, op.getOperand(0))); if (!isResultBuiltinCPtr) newOperands.push_back(arg); newOperands.append(op.getOperands().begin() + 1, op.getOperands().end()); - newOp = rewriter.create(loc, mlir::SymbolRefAttr{}, - newResultTypes, newOperands); + newOp = fir::CallOp::create(rewriter, loc, mlir::SymbolRefAttr{}, + newResultTypes, newOperands); } } @@ -191,8 +191,8 @@ class CallConversion : public mlir::OpRewritePattern { passArgPos = rewriter.getI32IntegerAttr(*op.getPassArgPos() + passArgShift); // TODO: propagate argument and result attributes (need to be shifted). - newOp = rewriter.create( - loc, newResultTypes, rewriter.getStringAttr(op.getMethod()), + newOp = fir::DispatchOp::create( + rewriter, loc, newResultTypes, rewriter.getStringAttr(op.getMethod()), op.getOperands()[0], newOperands, passArgPos, /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr, op.getProcedureAttrsAttr()); @@ -280,7 +280,7 @@ processReturnLikeOp(OpTy ret, mlir::Value newArg, // register pass, this is possible for fir.box results, or fir.record // with no length parameters. Simply store the result in the result // storage. at the return point. - rewriter.create(loc, resultValue, newArg); + fir::StoreOp::create(rewriter, loc, resultValue, newArg); rewriter.replaceOpWithNewOp(ret); } // Delete result old local storage if unused. @@ -337,8 +337,8 @@ class AddrOfOpConversion : public mlir::OpRewritePattern { newFuncTy = getCPtrFunctionType(oldFuncTy); else newFuncTy = getNewFunctionType(oldFuncTy, shouldBoxResult); - auto newAddrOf = rewriter.create(addrOf.getLoc(), newFuncTy, - addrOf.getSymbol()); + auto newAddrOf = fir::AddrOfOp::create(rewriter, addrOf.getLoc(), newFuncTy, + addrOf.getSymbol()); // Rather than converting all op a function pointer might transit through // (e.g calls, stores, loads, converts...), cast new type to the abstract // type. A conversion will be added when calling indirect calls of abstract @@ -397,7 +397,7 @@ class AbstractResultOpt if (mustEmboxResult(resultType, shouldBoxResult)) { auto bufferType = fir::ReferenceType::get(resultType); rewriter.setInsertionPointToStart(&func.front()); - newArg = rewriter.create(loc, bufferType, newArg); + newArg = fir::BoxAddrOp::create(rewriter, loc, bufferType, newArg); } patterns.insert(context, newArg); target.addDynamicallyLegalOp( diff --git a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp index b27c1b26dedb3..85403ad257657 100644 --- a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp +++ b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp @@ -48,12 +48,21 @@ static llvm::cl::opt llvm::cl::Hidden, llvm::cl::desc("Add TBAA tags to local allocations.")); +// Engineering option to triage TBAA tags attachment for accesses +// of allocatable entities. +static llvm::cl::opt localAllocsThreshold( + "local-alloc-tbaa-threshold", llvm::cl::init(0), llvm::cl::ReallyHidden, + llvm::cl::desc("If present, stops generating TBAA tags for accesses of " + "local allocations after N accesses in a module")); + namespace { /// Shared state per-module class PassState { public: - PassState(mlir::DominanceInfo &domInfo) : domInfo(domInfo) {} + PassState(mlir::DominanceInfo &domInfo, + std::optional localAllocsThreshold) + : domInfo(domInfo), localAllocsThreshold(localAllocsThreshold) {} /// memoised call to fir::AliasAnalysis::getSource inline const fir::AliasAnalysis::Source &getSource(mlir::Value value) { if (!analysisCache.contains(value)) @@ -84,6 +93,11 @@ class PassState { // (e.g. !fir.ref>}>>). bool typeReferencesDescriptor(mlir::Type type); + // Returns true if we can attach a TBAA tag to an access of an allocatable + // entities. It checks if localAllocsThreshold allows the next tag + // attachment. + bool attachLocalAllocTag(); + private: mlir::DominanceInfo &domInfo; fir::AliasAnalysis analysis; @@ -103,6 +117,8 @@ class PassState { // Local pass cache for derived types that contain descriptor // member(s), to avoid the cost of isRecordWithDescriptorMember(). llvm::DenseSet typesContainingDescriptors; + + std::optional localAllocsThreshold; }; // Process fir.dummy_scope operations in the given func: @@ -169,6 +185,19 @@ bool PassState::typeReferencesDescriptor(mlir::Type type) { return false; } +bool PassState::attachLocalAllocTag() { + if (!localAllocsThreshold) + return true; + if (*localAllocsThreshold == 0) { + LLVM_DEBUG(llvm::dbgs().indent(2) + << "WARN: not assigning TBAA tag for an allocated entity access " + "due to the threshold\n"); + return false; + } + --*localAllocsThreshold; + return true; +} + class AddAliasTagsPass : public fir::impl::AddAliasTagsBase { public: void runOnOperation() override; @@ -335,16 +364,16 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op, LLVM_DEBUG(llvm::dbgs().indent(2) << "WARN: unknown defining op for SourceKind::Allocate " << *op << "\n"); - } else if (source.isPointer()) { + } else if (source.isPointer() && state.attachLocalAllocTag()) { LLVM_DEBUG(llvm::dbgs().indent(2) << "Found reference to allocation at " << *op << "\n"); tag = state.getFuncTreeWithScope(func, scopeOp).targetDataTree.getTag(); - } else if (name) { + } else if (name && state.attachLocalAllocTag()) { LLVM_DEBUG(llvm::dbgs().indent(2) << "Found reference to allocation " << name << " at " << *op << "\n"); tag = state.getFuncTreeWithScope(func, scopeOp) .allocatedDataTree.getTag(*name); - } else { + } else if (state.attachLocalAllocTag()) { LLVM_DEBUG(llvm::dbgs().indent(2) << "WARN: couldn't find a name for allocation " << *op << "\n"); @@ -372,7 +401,9 @@ void AddAliasTagsPass::runOnOperation() { // thinks the pass operates on), then the real work of the pass is done in // runOnAliasInterface auto &domInfo = getAnalysis(); - PassState state(domInfo); + PassState state(domInfo, localAllocsThreshold.getPosition() + ? std::optional(localAllocsThreshold) + : std::nullopt); mlir::ModuleOp mod = getOperation(); mod.walk( diff --git a/flang/lib/Optimizer/Transforms/AffineDemotion.cpp b/flang/lib/Optimizer/Transforms/AffineDemotion.cpp index d45f855c9078e..f1c66a5bbcf8c 100644 --- a/flang/lib/Optimizer/Transforms/AffineDemotion.cpp +++ b/flang/lib/Optimizer/Transforms/AffineDemotion.cpp @@ -60,9 +60,10 @@ class AffineLoadConversion if (!maybeExpandedMap) return failure(); - auto coorOp = rewriter.create( - op.getLoc(), fir::ReferenceType::get(op.getResult().getType()), - adaptor.getMemref(), *maybeExpandedMap); + auto coorOp = fir::CoordinateOp::create( + rewriter, op.getLoc(), + fir::ReferenceType::get(op.getResult().getType()), adaptor.getMemref(), + *maybeExpandedMap); rewriter.replaceOpWithNewOp(op, coorOp.getResult()); return success(); @@ -83,8 +84,9 @@ class AffineStoreConversion if (!maybeExpandedMap) return failure(); - auto coorOp = rewriter.create( - op.getLoc(), fir::ReferenceType::get(op.getValueToStore().getType()), + auto coorOp = fir::CoordinateOp::create( + rewriter, op.getLoc(), + fir::ReferenceType::get(op.getValueToStore().getType()), adaptor.getMemref(), *maybeExpandedMap); rewriter.replaceOpWithNewOp(op, adaptor.getValue(), coorOp.getResult()); diff --git a/flang/lib/Optimizer/Transforms/AffinePromotion.cpp b/flang/lib/Optimizer/Transforms/AffinePromotion.cpp index ef82e400bea14..b032767eef6f0 100644 --- a/flang/lib/Optimizer/Transforms/AffinePromotion.cpp +++ b/flang/lib/Optimizer/Transforms/AffinePromotion.cpp @@ -366,8 +366,9 @@ static mlir::Type coordinateArrayElement(fir::ArrayCoorOp op) { static void populateIndexArgs(fir::ArrayCoorOp acoOp, fir::ShapeOp shape, SmallVectorImpl &indexArgs, mlir::PatternRewriter &rewriter) { - auto one = rewriter.create( - acoOp.getLoc(), rewriter.getIndexType(), rewriter.getIndexAttr(1)); + auto one = mlir::arith::ConstantOp::create(rewriter, acoOp.getLoc(), + rewriter.getIndexType(), + rewriter.getIndexAttr(1)); auto extents = shape.getExtents(); for (auto i = extents.begin(); i < extents.end(); i++) { indexArgs.push_back(one); @@ -379,8 +380,9 @@ static void populateIndexArgs(fir::ArrayCoorOp acoOp, fir::ShapeOp shape, static void populateIndexArgs(fir::ArrayCoorOp acoOp, fir::ShapeShiftOp shape, SmallVectorImpl &indexArgs, mlir::PatternRewriter &rewriter) { - auto one = rewriter.create( - acoOp.getLoc(), rewriter.getIndexType(), rewriter.getIndexAttr(1)); + auto one = mlir::arith::ConstantOp::create(rewriter, acoOp.getLoc(), + rewriter.getIndexType(), + rewriter.getIndexAttr(1)); auto extents = shape.getPairs(); for (auto i = extents.begin(); i < extents.end();) { indexArgs.push_back(*i++); @@ -422,13 +424,13 @@ createAffineOps(mlir::Value arrayRef, mlir::PatternRewriter &rewriter) { populateIndexArgs(acoOp, indexArgs, rewriter); - auto affineApply = rewriter.create( - acoOp.getLoc(), affineMap, indexArgs); + auto affineApply = affine::AffineApplyOp::create(rewriter, acoOp.getLoc(), + affineMap, indexArgs); auto arrayElementType = coordinateArrayElement(acoOp); auto newType = mlir::MemRefType::get({mlir::ShapedType::kDynamic}, arrayElementType); - auto arrayConvert = rewriter.create(acoOp.getLoc(), newType, - acoOp.getMemref()); + auto arrayConvert = fir::ConvertOp::create(rewriter, acoOp.getLoc(), newType, + acoOp.getMemref()); return std::make_pair(affineApply, arrayConvert); } @@ -495,7 +497,7 @@ class AffineLoopConversion : public mlir::OpRewritePattern { affineFor.getRegionIterArgs()); if (!results.empty()) { rewriter.setInsertionPointToEnd(affineFor.getBody()); - rewriter.create(resultOp->getLoc(), results); + affine::AffineYieldOp::create(rewriter, resultOp->getLoc(), results); } rewriter.finalizeOpModification(affineFor.getOperation()); @@ -525,8 +527,8 @@ class AffineLoopConversion : public mlir::OpRewritePattern { std::pair positiveConstantStep(fir::DoLoopOp op, int64_t step, mlir::PatternRewriter &rewriter) const { - auto affineFor = rewriter.create( - op.getLoc(), ValueRange(op.getLowerBound()), + auto affineFor = affine::AffineForOp::create( + rewriter, op.getLoc(), ValueRange(op.getLowerBound()), mlir::AffineMap::get(0, 1, mlir::getAffineSymbolExpr(0, op.getContext())), ValueRange(op.getUpperBound()), @@ -543,24 +545,24 @@ class AffineLoopConversion : public mlir::OpRewritePattern { auto step = mlir::getAffineSymbolExpr(2, op.getContext()); mlir::AffineMap upperBoundMap = mlir::AffineMap::get( 0, 3, (upperBound - lowerBound + step).floorDiv(step)); - auto genericUpperBound = rewriter.create( - op.getLoc(), upperBoundMap, + auto genericUpperBound = affine::AffineApplyOp::create( + rewriter, op.getLoc(), upperBoundMap, ValueRange({op.getLowerBound(), op.getUpperBound(), op.getStep()})); auto actualIndexMap = mlir::AffineMap::get( 1, 2, (lowerBound + mlir::getAffineDimExpr(0, op.getContext())) * mlir::getAffineSymbolExpr(1, op.getContext())); - auto affineFor = rewriter.create( - op.getLoc(), ValueRange(), + auto affineFor = affine::AffineForOp::create( + rewriter, op.getLoc(), ValueRange(), AffineMap::getConstantMap(0, op.getContext()), genericUpperBound.getResult(), mlir::AffineMap::get(0, 1, 1 + mlir::getAffineSymbolExpr(0, op.getContext())), 1, op.getIterOperands()); rewriter.setInsertionPointToStart(affineFor.getBody()); - auto actualIndex = rewriter.create( - op.getLoc(), actualIndexMap, + auto actualIndex = affine::AffineApplyOp::create( + rewriter, op.getLoc(), actualIndexMap, ValueRange( {affineFor.getInductionVar(), op.getLowerBound(), op.getStep()})); return std::make_pair(affineFor, actualIndex.getResult()); @@ -588,8 +590,8 @@ class AffineIfConversion : public mlir::OpRewritePattern { << "AffineIfConversion: couldn't calculate affine condition\n";); return failure(); } - auto affineIf = rewriter.create( - op.getLoc(), affineCondition.getIntegerSet(), + auto affineIf = affine::AffineIfOp::create( + rewriter, op.getLoc(), affineCondition.getIntegerSet(), affineCondition.getAffineArgs(), !op.getElseRegion().empty()); rewriter.startOpModification(affineIf); affineIf.getThenBlock()->getOperations().splice( diff --git a/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp b/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp index 8544d17f62248..247ba953f3265 100644 --- a/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp +++ b/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp @@ -856,7 +856,7 @@ static bool getAdjustedExtents(mlir::Location loc, auto idxTy = rewriter.getIndexType(); if (isAssumedSize(result)) { // Use slice information to compute the extent of the column. - auto one = rewriter.create(loc, 1); + auto one = mlir::arith::ConstantIndexOp::create(rewriter, loc, 1); mlir::Value size = one; if (mlir::Value sliceArg = arrLoad.getSlice()) { if (auto sliceOp = @@ -896,14 +896,14 @@ static mlir::Value getOrReadExtentsAndShapeOp( mlir::cast(dyn_cast_ptrOrBoxEleTy(boxTy)).getDimension(); auto idxTy = rewriter.getIndexType(); for (decltype(rank) dim = 0; dim < rank; ++dim) { - auto dimVal = rewriter.create(loc, dim); - auto dimInfo = rewriter.create(loc, idxTy, idxTy, idxTy, - arrLoad.getMemref(), dimVal); + auto dimVal = mlir::arith::ConstantIndexOp::create(rewriter, loc, dim); + auto dimInfo = BoxDimsOp::create(rewriter, loc, idxTy, idxTy, idxTy, + arrLoad.getMemref(), dimVal); result.emplace_back(dimInfo.getResult(1)); } if (!arrLoad.getShape()) { auto shapeType = ShapeType::get(rewriter.getContext(), rank); - return rewriter.create(loc, shapeType, result); + return ShapeOp::create(rewriter, loc, shapeType, result); } auto shiftOp = arrLoad.getShape().getDefiningOp(); auto shapeShiftType = ShapeShiftType::get(rewriter.getContext(), rank); @@ -912,8 +912,8 @@ static mlir::Value getOrReadExtentsAndShapeOp( shapeShiftOperands.push_back(lb); shapeShiftOperands.push_back(extent); } - return rewriter.create(loc, shapeShiftType, - shapeShiftOperands); + return ShapeShiftOp::create(rewriter, loc, shapeShiftType, + shapeShiftOperands); } copyUsingSlice = getAdjustedExtents(loc, rewriter, arrLoad, result, arrLoad.getShape()); @@ -952,13 +952,13 @@ static mlir::Value genCoorOp(mlir::PatternRewriter &rewriter, auto module = load->getParentOfType(); FirOpBuilder builder(rewriter, module); auto typeparams = getTypeParamsIfRawData(loc, builder, load, alloc.getType()); - mlir::Value result = rewriter.create( - loc, eleTy, alloc, shape, slice, + mlir::Value result = ArrayCoorOp::create( + rewriter, loc, eleTy, alloc, shape, slice, llvm::ArrayRef{originated}.take_front(dimension), typeparams); if (dimension < originated.size()) - result = rewriter.create( - loc, resTy, result, + result = fir::CoordinateOp::create( + rewriter, loc, resTy, result, llvm::ArrayRef{originated}.drop_front(dimension)); return result; } @@ -971,13 +971,13 @@ static mlir::Value getCharacterLen(mlir::Location loc, FirOpBuilder &builder, // The loaded array is an emboxed value. Get the CHARACTER length from // the box value. auto eleSzInBytes = - builder.create(loc, charLenTy, load.getMemref()); + BoxEleSizeOp::create(builder, loc, charLenTy, load.getMemref()); auto kindSize = builder.getKindMap().getCharacterBitsize(charTy.getFKind()); auto kindByteSize = builder.createIntegerConstant(loc, charLenTy, kindSize / 8); - return builder.create(loc, eleSzInBytes, - kindByteSize); + return mlir::arith::DivSIOp::create(builder, loc, eleSzInBytes, + kindByteSize); } // The loaded array is a (set of) unboxed values. If the CHARACTER's // length is not a constant, it must be provided as a type parameter to @@ -1003,11 +1003,11 @@ void genArrayCopy(mlir::Location loc, mlir::PatternRewriter &rewriter, auto idxTy = rewriter.getIndexType(); // Build loop nest from column to row. for (auto sh : llvm::reverse(extents)) { - auto ubi = rewriter.create(loc, idxTy, sh); - auto zero = rewriter.create(loc, 0); - auto one = rewriter.create(loc, 1); - auto ub = rewriter.create(loc, idxTy, ubi, one); - auto loop = rewriter.create(loc, zero, ub, one); + auto ubi = ConvertOp::create(rewriter, loc, idxTy, sh); + auto zero = mlir::arith::ConstantIndexOp::create(rewriter, loc, 0); + auto one = mlir::arith::ConstantIndexOp::create(rewriter, loc, 1); + auto ub = mlir::arith::SubIOp::create(rewriter, loc, idxTy, ubi, one); + auto loop = DoLoopOp::create(rewriter, loc, zero, ub, one); rewriter.setInsertionPointToStart(loop.getBody()); indices.push_back(loop.getInductionVar()); } @@ -1015,13 +1015,13 @@ void genArrayCopy(mlir::Location loc, mlir::PatternRewriter &rewriter, std::reverse(indices.begin(), indices.end()); auto module = arrLoad->getParentOfType(); FirOpBuilder builder(rewriter, module); - auto fromAddr = rewriter.create( - loc, getEleTy(src.getType()), src, shapeOp, + auto fromAddr = ArrayCoorOp::create( + rewriter, loc, getEleTy(src.getType()), src, shapeOp, CopyIn && copyUsingSlice ? sliceOp : mlir::Value{}, factory::originateIndices(loc, rewriter, src.getType(), shapeOp, indices), getTypeParamsIfRawData(loc, builder, arrLoad, src.getType())); - auto toAddr = rewriter.create( - loc, getEleTy(dst.getType()), dst, shapeOp, + auto toAddr = ArrayCoorOp::create( + rewriter, loc, getEleTy(dst.getType()), dst, shapeOp, !CopyIn && copyUsingSlice ? sliceOp : mlir::Value{}, factory::originateIndices(loc, rewriter, dst.getType(), shapeOp, indices), getTypeParamsIfRawData(loc, builder, arrLoad, dst.getType())); @@ -1093,15 +1093,16 @@ allocateArrayTemp(mlir::Location loc, mlir::PatternRewriter &rewriter, findNonconstantExtents(baseType, extents); llvm::SmallVector typeParams = genArrayLoadTypeParameters(loc, rewriter, load); - mlir::Value allocmem = rewriter.create( - loc, dyn_cast_ptrOrBoxEleTy(baseType), typeParams, nonconstantExtents); + mlir::Value allocmem = + AllocMemOp::create(rewriter, loc, dyn_cast_ptrOrBoxEleTy(baseType), + typeParams, nonconstantExtents); mlir::Type eleType = fir::unwrapSequenceType(fir::unwrapPassByRefType(baseType)); if (fir::isRecordWithAllocatableMember(eleType)) { // The allocatable component descriptors need to be set to a clean // deallocated status before anything is done with them. - mlir::Value box = rewriter.create( - loc, fir::BoxType::get(allocmem.getType()), allocmem, shape, + mlir::Value box = fir::EmboxOp::create( + rewriter, loc, fir::BoxType::get(allocmem.getType()), allocmem, shape, /*slice=*/mlir::Value{}, typeParams); auto module = load->getParentOfType(); FirOpBuilder builder(rewriter, module); @@ -1111,12 +1112,12 @@ allocateArrayTemp(mlir::Location loc, mlir::PatternRewriter &rewriter, auto cleanup = [=](mlir::PatternRewriter &r) { FirOpBuilder builder(r, module); runtime::genDerivedTypeDestroy(builder, loc, box); - r.create(loc, allocmem); + FreeMemOp::create(r, loc, allocmem); }; return {allocmem, cleanup}; } auto cleanup = [=](mlir::PatternRewriter &r) { - r.create(loc, allocmem); + FreeMemOp::create(r, loc, allocmem); }; return {allocmem, cleanup}; } @@ -1257,7 +1258,7 @@ class ArrayUpdateConversion : public ArrayUpdateConversionBase { if (auto inEleTy = dyn_cast_ptrEleTy(input.getType())) { emitFatalError(loc, "array_update on references not supported"); } else { - rewriter.create(loc, input, coor); + fir::StoreOp::create(rewriter, loc, input, coor); } }; auto lhsEltRefType = toRefType(update.getMerge().getType()); @@ -1368,7 +1369,7 @@ class ArrayAmendConversion : public mlir::OpRewritePattern { auto *op = amend.getOperation(); rewriter.setInsertionPoint(op); auto loc = amend.getLoc(); - auto undef = rewriter.create(loc, amend.getType()); + auto undef = UndefOp::create(rewriter, loc, amend.getType()); rewriter.replaceOp(amend, undef.getResult()); return mlir::success(); } diff --git a/flang/lib/Optimizer/Transforms/AssumedRankOpConversion.cpp b/flang/lib/Optimizer/Transforms/AssumedRankOpConversion.cpp index 6af1cb988a4c1..4c7b228eefeb5 100644 --- a/flang/lib/Optimizer/Transforms/AssumedRankOpConversion.cpp +++ b/flang/lib/Optimizer/Transforms/AssumedRankOpConversion.cpp @@ -88,8 +88,8 @@ class ReboxAssumedRankConv (fir::isPolymorphicType(oldBoxType) || (newEleType != oldBoxType.unwrapInnerType())) && !fir::isPolymorphicType(newBoxType)) { - newDtype = builder.create( - loc, mlir::TypeAttr::get(newDerivedType)); + newDtype = fir::TypeDescOp::create(builder, loc, + mlir::TypeAttr::get(newDerivedType)); } else { newDtype = builder.createNullConstant(loc); } @@ -103,7 +103,7 @@ class ReboxAssumedRankConv rebox.getBox(), newDtype, newAttribute, lowerBoundModifier); - mlir::Value descValue = builder.create(loc, tempDesc); + mlir::Value descValue = fir::LoadOp::create(builder, loc, tempDesc); mlir::Value castDesc = builder.createConvert(loc, newBoxType, descValue); rewriter.replaceOp(rebox, castDesc); return mlir::success(); diff --git a/flang/lib/Optimizer/Transforms/CUFAddConstructor.cpp b/flang/lib/Optimizer/Transforms/CUFAddConstructor.cpp index 2dd6950b34897..baa8e591ee162 100644 --- a/flang/lib/Optimizer/Transforms/CUFAddConstructor.cpp +++ b/flang/lib/Optimizer/Transforms/CUFAddConstructor.cpp @@ -68,25 +68,26 @@ struct CUFAddConstructor // Symbol reference to CUFRegisterAllocator. builder.setInsertionPointToEnd(mod.getBody()); - auto registerFuncOp = builder.create( - loc, RTNAME_STRING(CUFRegisterAllocator), funcTy); + auto registerFuncOp = mlir::LLVM::LLVMFuncOp::create( + builder, loc, RTNAME_STRING(CUFRegisterAllocator), funcTy); registerFuncOp.setVisibility(mlir::SymbolTable::Visibility::Private); auto cufRegisterAllocatorRef = mlir::SymbolRefAttr::get( mod.getContext(), RTNAME_STRING(CUFRegisterAllocator)); builder.setInsertionPointToEnd(mod.getBody()); // Create the constructor function that call CUFRegisterAllocator. - auto func = builder.create(loc, cudaFortranCtorName, - funcTy); + auto func = mlir::LLVM::LLVMFuncOp::create(builder, loc, + cudaFortranCtorName, funcTy); func.setLinkage(mlir::LLVM::Linkage::Internal); builder.setInsertionPointToStart(func.addEntryBlock(builder)); - builder.create(loc, funcTy, cufRegisterAllocatorRef); + mlir::LLVM::CallOp::create(builder, loc, funcTy, cufRegisterAllocatorRef); auto gpuMod = symTab.lookup(cudaDeviceModuleName); if (gpuMod) { auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(ctx); - auto registeredMod = builder.create( - loc, llvmPtrTy, mlir::SymbolRefAttr::get(ctx, gpuMod.getName())); + auto registeredMod = cuf::RegisterModuleOp::create( + builder, loc, llvmPtrTy, + mlir::SymbolRefAttr::get(ctx, gpuMod.getName())); fir::LLVMTypeConverter typeConverter(mod, /*applyTBAA=*/false, /*forceUnifiedTBAATree=*/false, *dl); @@ -96,7 +97,8 @@ struct CUFAddConstructor auto kernelName = mlir::SymbolRefAttr::get( builder.getStringAttr(cudaDeviceModuleName), {mlir::SymbolRefAttr::get(builder.getContext(), func.getName())}); - builder.create(loc, kernelName, registeredMod); + cuf::RegisterKernelOp::create(builder, loc, kernelName, + registeredMod); } } @@ -140,19 +142,19 @@ struct CUFAddConstructor auto sizeVal = builder.createIntegerConstant(loc, idxTy, *size); // Global variable address - mlir::Value addr = builder.create( - loc, globalOp.resultType(), globalOp.getSymbol()); + mlir::Value addr = fir::AddrOfOp::create( + builder, loc, globalOp.resultType(), globalOp.getSymbol()); llvm::SmallVector args{fir::runtime::createArguments( builder, loc, fTy, registeredMod, addr, gblName, sizeVal)}; - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); } break; default: break; } } } - builder.create(loc, mlir::ValueRange{}); + mlir::LLVM::ReturnOp::create(builder, loc, mlir::ValueRange{}); // Create the llvm.global_ctor with the function. // TODO: We might want to have a utility that retrieve it if already @@ -165,8 +167,8 @@ struct CUFAddConstructor llvm::SmallVector data; priorities.push_back(0); data.push_back(mlir::LLVM::ZeroAttr::get(mod.getContext())); - builder.create( - mod.getLoc(), builder.getArrayAttr(funcs), + mlir::LLVM::GlobalCtorsOp::create( + builder, mod.getLoc(), builder.getArrayAttr(funcs), builder.getI32ArrayAttr(priorities), builder.getArrayAttr(data)); } }; diff --git a/flang/lib/Optimizer/Transforms/CUFComputeSharedMemoryOffsetsAndSize.cpp b/flang/lib/Optimizer/Transforms/CUFComputeSharedMemoryOffsetsAndSize.cpp index f6381ef8a8a21..5e910f7da6472 100644 --- a/flang/lib/Optimizer/Transforms/CUFComputeSharedMemoryOffsetsAndSize.cpp +++ b/flang/lib/Optimizer/Transforms/CUFComputeSharedMemoryOffsetsAndSize.cpp @@ -93,10 +93,11 @@ struct CUFComputeSharedMemoryOffsetsAndSize mlir::Value dynSize = builder.createIntegerConstant(loc, idxTy, tySize); for (auto extent : sharedOp.getShape()) - dynSize = builder.create(loc, dynSize, extent); + dynSize = + mlir::arith::MulIOp::create(builder, loc, dynSize, extent); if (crtDynOffset) - crtDynOffset = - builder.create(loc, crtDynOffset, dynSize); + crtDynOffset = mlir::arith::AddIOp::create(builder, loc, + crtDynOffset, dynSize); else crtDynOffset = dynSize; @@ -142,9 +143,9 @@ struct CUFComputeSharedMemoryOffsetsAndSize fir::GlobalOp::getDataAttrAttrName(globalOpName), cuf::DataAttributeAttr::get(gpuMod.getContext(), cuf::DataAttribute::Shared))); - auto sharedMem = builder.create( - funcOp.getLoc(), sharedMemGlobalName, false, false, sharedMemType, - init, linkage, attrs); + auto sharedMem = fir::GlobalOp::create( + builder, funcOp.getLoc(), sharedMemGlobalName, false, false, + sharedMemType, init, linkage, attrs); sharedMem.setAlignment(alignment); } } diff --git a/flang/lib/Optimizer/Transforms/CUFDeviceGlobal.cpp b/flang/lib/Optimizer/Transforms/CUFDeviceGlobal.cpp index bfb0daeacb8c3..35badb6eadb1c 100644 --- a/flang/lib/Optimizer/Transforms/CUFDeviceGlobal.cpp +++ b/flang/lib/Optimizer/Transforms/CUFDeviceGlobal.cpp @@ -53,21 +53,26 @@ static void processAddrOfOp(fir::AddrOfOp addrOfOp, } } +static void processTypeDescriptor(fir::RecordType recTy, + mlir::SymbolTable &symbolTable, + llvm::DenseSet &candidates) { + if (auto globalOp = symbolTable.lookup( + fir::NameUniquer::getTypeDescriptorName(recTy.getName()))) { + if (!candidates.contains(globalOp)) { + globalOp.walk([&](fir::AddrOfOp op) { + processAddrOfOp(op, symbolTable, candidates, + /*recurseInGlobal=*/true); + }); + candidates.insert(globalOp); + } + } +} + static void processEmboxOp(fir::EmboxOp emboxOp, mlir::SymbolTable &symbolTable, llvm::DenseSet &candidates) { if (auto recTy = mlir::dyn_cast( - fir::unwrapRefType(emboxOp.getMemref().getType()))) { - if (auto globalOp = symbolTable.lookup( - fir::NameUniquer::getTypeDescriptorName(recTy.getName()))) { - if (!candidates.contains(globalOp)) { - globalOp.walk([&](fir::AddrOfOp op) { - processAddrOfOp(op, symbolTable, candidates, - /*recurseInGlobal=*/true); - }); - candidates.insert(globalOp); - } - } - } + fir::unwrapRefType(emboxOp.getMemref().getType()))) + processTypeDescriptor(recTy, symbolTable, candidates); } static void @@ -85,6 +90,17 @@ prepareImplicitDeviceGlobals(mlir::func::FuncOp funcOp, } } +static void +processPotentialTypeDescriptor(mlir::Type candidateType, + mlir::SymbolTable &symbolTable, + llvm::DenseSet &candidates) { + if (auto boxTy = mlir::dyn_cast(candidateType)) + candidateType = boxTy.getEleTy(); + candidateType = fir::unwrapSequenceType(fir::unwrapRefType(candidateType)); + if (auto recTy = mlir::dyn_cast(candidateType)) + processTypeDescriptor(recTy, symbolTable, candidates); +} + class CUFDeviceGlobal : public fir::impl::CUFDeviceGlobalBase { public: void runOnOperation() override { @@ -115,6 +131,8 @@ class CUFDeviceGlobal : public fir::impl::CUFDeviceGlobalBase { for (auto globalOp : mod.getOps()) { if (cuf::isRegisteredDeviceGlobal(globalOp)) { candidates.insert(globalOp); + processPotentialTypeDescriptor(globalOp.getType(), parentSymTable, + candidates); } else if (globalOp.getConstant() && mlir::isa( fir::unwrapRefType(globalOp.resultType()))) { diff --git a/flang/lib/Optimizer/Transforms/CUFGPUToLLVMConversion.cpp b/flang/lib/Optimizer/Transforms/CUFGPUToLLVMConversion.cpp index fe69ffa8350af..a40ed95391c3a 100644 --- a/flang/lib/Optimizer/Transforms/CUFGPUToLLVMConversion.cpp +++ b/flang/lib/Optimizer/Transforms/CUFGPUToLLVMConversion.cpp @@ -46,27 +46,28 @@ static mlir::Value createKernelArgArray(mlir::Location loc, auto structTy = mlir::LLVM::LLVMStructType::getLiteral(ctx, structTypes); auto ptrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext()); mlir::Type i32Ty = rewriter.getI32Type(); - auto zero = rewriter.create( - loc, i32Ty, rewriter.getIntegerAttr(i32Ty, 0)); - auto one = rewriter.create( - loc, i32Ty, rewriter.getIntegerAttr(i32Ty, 1)); + auto zero = mlir::LLVM::ConstantOp::create(rewriter, loc, i32Ty, + rewriter.getIntegerAttr(i32Ty, 0)); + auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, i32Ty, + rewriter.getIntegerAttr(i32Ty, 1)); mlir::Value argStruct = - rewriter.create(loc, ptrTy, structTy, one); - auto size = rewriter.create( - loc, i32Ty, rewriter.getIntegerAttr(i32Ty, structTypes.size())); + mlir::LLVM::AllocaOp::create(rewriter, loc, ptrTy, structTy, one); + auto size = mlir::LLVM::ConstantOp::create( + rewriter, loc, i32Ty, rewriter.getIntegerAttr(i32Ty, structTypes.size())); mlir::Value argArray = - rewriter.create(loc, ptrTy, ptrTy, size); + mlir::LLVM::AllocaOp::create(rewriter, loc, ptrTy, ptrTy, size); for (auto [i, arg] : llvm::enumerate(operands)) { - auto indice = rewriter.create( - loc, i32Ty, rewriter.getIntegerAttr(i32Ty, i)); - mlir::Value structMember = rewriter.create( - loc, ptrTy, structTy, argStruct, - mlir::ArrayRef({zero, indice})); - rewriter.create(loc, arg, structMember); - mlir::Value arrayMember = rewriter.create( - loc, ptrTy, ptrTy, argArray, mlir::ArrayRef({indice})); - rewriter.create(loc, structMember, arrayMember); + auto indice = mlir::LLVM::ConstantOp::create( + rewriter, loc, i32Ty, rewriter.getIntegerAttr(i32Ty, i)); + mlir::Value structMember = + LLVM::GEPOp::create(rewriter, loc, ptrTy, structTy, argStruct, + mlir::ArrayRef({zero, indice})); + LLVM::StoreOp::create(rewriter, loc, arg, structMember); + mlir::Value arrayMember = + LLVM::GEPOp::create(rewriter, loc, ptrTy, ptrTy, argArray, + mlir::ArrayRef({indice})); + LLVM::StoreOp::create(rewriter, loc, structMember, arrayMember); } return argArray; } @@ -94,8 +95,8 @@ struct GPULaunchKernelConversion mlir::Value dynamicMemorySize = op.getDynamicSharedMemorySize(); mlir::Type i32Ty = rewriter.getI32Type(); if (!dynamicMemorySize) - dynamicMemorySize = rewriter.create( - loc, i32Ty, rewriter.getIntegerAttr(i32Ty, 0)); + dynamicMemorySize = mlir::LLVM::ConstantOp::create( + rewriter, loc, i32Ty, rewriter.getIntegerAttr(i32Ty, 0)); mlir::Value kernelArgs = createKernelArgArray(loc, adaptor.getKernelOperands(), rewriter); @@ -108,17 +109,17 @@ struct GPULaunchKernelConversion if (!funcOp) return mlir::failure(); kernelPtr = - rewriter.create(loc, ptrTy, funcOp.getName()); + LLVM::AddressOfOp::create(rewriter, loc, ptrTy, funcOp.getName()); } else { kernelPtr = - rewriter.create(loc, ptrTy, kernel.getName()); + LLVM::AddressOfOp::create(rewriter, loc, ptrTy, kernel.getName()); } auto llvmIntPtrType = mlir::IntegerType::get( ctx, this->getTypeConverter()->getPointerBitwidth(0)); auto voidTy = mlir::LLVM::LLVMVoidType::get(ctx); - mlir::Value nullPtr = rewriter.create(loc, ptrTy); + mlir::Value nullPtr = LLVM::ZeroOp::create(rewriter, loc, ptrTy); if (op.hasClusterSize()) { auto funcOp = mod.lookupSymbol( @@ -134,8 +135,8 @@ struct GPULaunchKernelConversion if (!funcOp) { mlir::OpBuilder::InsertionGuard insertGuard(rewriter); rewriter.setInsertionPointToStart(mod.getBody()); - auto launchKernelFuncOp = rewriter.create( - loc, RTNAME_STRING(CUFLaunchClusterKernel), funcTy); + auto launchKernelFuncOp = mlir::LLVM::LLVMFuncOp::create( + rewriter, loc, RTNAME_STRING(CUFLaunchClusterKernel), funcTy); launchKernelFuncOp.setVisibility( mlir::SymbolTable::Visibility::Private); } @@ -148,8 +149,8 @@ struct GPULaunchKernelConversion stream = adaptor.getAsyncDependencies().front(); } - rewriter.create( - loc, funcTy, cufLaunchClusterKernel, + mlir::LLVM::CallOp::create( + rewriter, loc, funcTy, cufLaunchClusterKernel, mlir::ValueRange{kernelPtr, adaptor.getClusterSizeX(), adaptor.getClusterSizeY(), adaptor.getClusterSizeZ(), adaptor.getGridSizeX(), adaptor.getGridSizeY(), @@ -178,7 +179,7 @@ struct GPULaunchKernelConversion mlir::OpBuilder::InsertionGuard insertGuard(rewriter); rewriter.setInsertionPointToStart(mod.getBody()); auto launchKernelFuncOp = - rewriter.create(loc, fctName, funcTy); + mlir::LLVM::LLVMFuncOp::create(rewriter, loc, fctName, funcTy); launchKernelFuncOp.setVisibility( mlir::SymbolTable::Visibility::Private); } @@ -191,8 +192,8 @@ struct GPULaunchKernelConversion stream = adaptor.getAsyncDependencies().front(); } - rewriter.create( - loc, funcTy, cufLaunchKernel, + mlir::LLVM::CallOp::create( + rewriter, loc, funcTy, cufLaunchKernel, mlir::ValueRange{kernelPtr, adaptor.getGridSizeX(), adaptor.getGridSizeY(), adaptor.getGridSizeZ(), adaptor.getBlockSizeX(), adaptor.getBlockSizeY(), @@ -222,11 +223,11 @@ static mlir::Value createAddressOfOp(mlir::ConversionPatternRewriter &rewriter, auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get( rewriter.getContext(), mlir::NVVM::NVVMMemorySpace::kSharedMemorySpace); if (auto g = gpuMod.lookupSymbol(sharedGlobalName)) - return rewriter.create(loc, llvmPtrTy, - g.getSymName()); + return mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy, + g.getSymName()); if (auto g = gpuMod.lookupSymbol(sharedGlobalName)) - return rewriter.create(loc, llvmPtrTy, - g.getSymName()); + return mlir::LLVM::AddressOfOp::create(rewriter, loc, llvmPtrTy, + g.getSymName()); return {}; } @@ -255,13 +256,13 @@ struct CUFSharedMemoryOpConversion if (!sharedGlobalAddr) mlir::emitError(loc, "Could not find the shared global operation\n"); - auto castPtr = rewriter.create( - loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), + auto castPtr = mlir::LLVM::AddrSpaceCastOp::create( + rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), sharedGlobalAddr); mlir::Type baseType = castPtr->getResultTypes().front(); llvm::SmallVector gepArgs = {op.getOffset()}; - mlir::Value shmemPtr = rewriter.create( - loc, baseType, rewriter.getI8Type(), castPtr, gepArgs); + mlir::Value shmemPtr = mlir::LLVM::GEPOp::create( + rewriter, loc, baseType, rewriter.getI8Type(), castPtr, gepArgs); rewriter.replaceOp(op, {shmemPtr}); return mlir::success(); } diff --git a/flang/lib/Optimizer/Transforms/CUFOpConversion.cpp b/flang/lib/Optimizer/Transforms/CUFOpConversion.cpp index 750569c126642..cd7d33091f345 100644 --- a/flang/lib/Optimizer/Transforms/CUFOpConversion.cpp +++ b/flang/lib/Optimizer/Transforms/CUFOpConversion.cpp @@ -89,7 +89,7 @@ static mlir::Value createConvertOp(mlir::PatternRewriter &rewriter, mlir::Location loc, mlir::Type toTy, mlir::Value val) { if (val.getType() != toTy) - return rewriter.create(loc, toTy, val); + return fir::ConvertOp::create(rewriter, loc, toTy, val); return val; } @@ -118,7 +118,7 @@ static mlir::LogicalResult convertOpToCall(OpTy op, errmsg = op.getErrmsg(); } else { mlir::Type boxNoneTy = fir::BoxType::get(builder.getNoneType()); - errmsg = builder.create(loc, boxNoneTy).getResult(); + errmsg = fir::AbsentOp::create(builder, loc, boxNoneTy).getResult(); } llvm::SmallVector args; if constexpr (std::is_same_v) { @@ -148,7 +148,7 @@ static mlir::LogicalResult convertOpToCall(OpTy op, fir::runtime::createArguments(builder, loc, fTy, op.getBox(), hasStat, errmsg, sourceFile, sourceLine); } - auto callOp = builder.create(loc, func, args); + auto callOp = fir::CallOp::create(builder, loc, func, args); rewriter.replaceOp(op, callOp); return mlir::success(); } @@ -301,10 +301,11 @@ struct CUFAllocOpConversion : public mlir::OpRewritePattern { if (inDeviceContext(op.getOperation())) { // In device context just replace the cuf.alloc operation with a fir.alloc // the cuf.free will be removed. - auto allocaOp = rewriter.create( - loc, op.getInType(), op.getUniqName() ? *op.getUniqName() : "", - op.getBindcName() ? *op.getBindcName() : "", op.getTypeparams(), - op.getShape()); + auto allocaOp = + fir::AllocaOp::create(rewriter, loc, op.getInType(), + op.getUniqName() ? *op.getUniqName() : "", + op.getBindcName() ? *op.getBindcName() : "", + op.getTypeparams(), op.getShape()); allocaOp->setAttr(cuf::getDataAttrName(), op.getDataAttrAttr()); rewriter.replaceOp(op, allocaOp); return mlir::success(); @@ -338,14 +339,15 @@ struct CUFAllocOpConversion : public mlir::OpRewritePattern { assert(!op.getShape().empty() && "expect shape with dynamic arrays"); nbElem = builder.loadIfRef(loc, op.getShape()[0]); for (unsigned i = 1; i < op.getShape().size(); ++i) { - nbElem = rewriter.create( - loc, nbElem, builder.loadIfRef(loc, op.getShape()[i])); + nbElem = mlir::arith::MulIOp::create( + rewriter, loc, nbElem, + builder.loadIfRef(loc, op.getShape()[i])); } } else { nbElem = builder.createIntegerConstant(loc, builder.getIndexType(), seqTy.getConstantArraySize()); } - bytes = rewriter.create(loc, nbElem, width); + bytes = mlir::arith::MulIOp::create(rewriter, loc, nbElem, width); } else if (fir::isa_derived(op.getInType())) { mlir::Type structTy = typeConverter->convertType(op.getInType()); std::size_t structSize = dl->getTypeSizeInBits(structTy) / 8; @@ -363,7 +365,7 @@ struct CUFAllocOpConversion : public mlir::OpRewritePattern { loc, builder.getI32Type(), getMemType(op.getDataAttr())); llvm::SmallVector args{fir::runtime::createArguments( builder, loc, fTy, bytes, memTy, sourceFile, sourceLine)}; - auto callOp = builder.create(loc, func, args); + auto callOp = fir::CallOp::create(builder, loc, func, args); callOp->setAttr(cuf::getDataAttrName(), op.getDataAttrAttr()); auto convOp = builder.createConvert(loc, op.getResult().getType(), callOp.getResult(0)); @@ -386,7 +388,7 @@ struct CUFAllocOpConversion : public mlir::OpRewritePattern { llvm::SmallVector args{fir::runtime::createArguments( builder, loc, fTy, sizeInBytes, sourceFile, sourceLine)}; - auto callOp = builder.create(loc, func, args); + auto callOp = fir::CallOp::create(builder, loc, func, args); callOp->setAttr(cuf::getDataAttrName(), op.getDataAttrAttr()); auto convOp = builder.createConvert(loc, op.getResult().getType(), callOp.getResult(0)); @@ -414,8 +416,9 @@ struct CUFDeviceAddressOpConversion op.getHostSymbol().getRootReference().getValue())) { auto mod = op->getParentOfType(); mlir::Location loc = op.getLoc(); - auto hostAddr = rewriter.create( - loc, fir::ReferenceType::get(global.getType()), op.getHostSymbol()); + auto hostAddr = fir::AddrOfOp::create( + rewriter, loc, fir::ReferenceType::get(global.getType()), + op.getHostSymbol()); fir::FirOpBuilder builder(rewriter, mod); mlir::func::FuncOp callee = fir::runtime::getRuntimeFunc(loc, @@ -428,7 +431,7 @@ struct CUFDeviceAddressOpConversion fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); llvm::SmallVector args{fir::runtime::createArguments( builder, loc, fTy, conv, sourceFile, sourceLine)}; - auto call = rewriter.create(loc, callee, args); + auto call = fir::CallOp::create(rewriter, loc, callee, args); mlir::Value addr = createConvertOp(rewriter, loc, hostAddr.getType(), call->getResult(0)); rewriter.replaceOp(op, addr.getDefiningOp()); @@ -456,8 +459,8 @@ struct DeclareOpConversion : public mlir::OpRewritePattern { addrOfOp.getSymbol().getRootReference().getValue())) { if (cuf::isRegisteredDeviceGlobal(global)) { rewriter.setInsertionPointAfter(addrOfOp); - mlir::Value devAddr = rewriter.create( - op.getLoc(), addrOfOp.getType(), addrOfOp.getSymbol()); + mlir::Value devAddr = cuf::DeviceAddressOp::create( + rewriter, op.getLoc(), addrOfOp.getType(), addrOfOp.getSymbol()); rewriter.startOpModification(op); op.getMemrefMutable().assign(devAddr); rewriter.finalizeOpModification(op); @@ -502,7 +505,7 @@ struct CUFFreeOpConversion : public mlir::OpRewritePattern { loc, builder.getI32Type(), getMemType(op.getDataAttr())); llvm::SmallVector args{fir::runtime::createArguments( builder, loc, fTy, op.getDevptr(), memTy, sourceFile, sourceLine)}; - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); rewriter.eraseOp(op); return mlir::success(); } @@ -515,7 +518,7 @@ struct CUFFreeOpConversion : public mlir::OpRewritePattern { fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); llvm::SmallVector args{fir::runtime::createArguments( builder, loc, fTy, op.getDevptr(), sourceFile, sourceLine)}; - auto callOp = builder.create(loc, func, args); + auto callOp = fir::CallOp::create(builder, loc, func, args); callOp->setAttr(cuf::getDataAttrName(), op.getDataAttrAttr()); rewriter.eraseOp(op); return mlir::success(); @@ -558,18 +561,18 @@ static mlir::Value emboxSrc(mlir::PatternRewriter &rewriter, srcTy = fir::LogicalType::get(rewriter.getContext(), 4); src = createConvertOp(rewriter, loc, srcTy, src); addr = builder.createTemporary(loc, srcTy); - builder.create(loc, src, addr); + fir::StoreOp::create(builder, loc, src, addr); } else { if (dstEleTy && fir::isa_trivial(dstEleTy) && srcTy != dstEleTy) { // Use dstEleTy and convert to avoid assign mismatch. addr = builder.createTemporary(loc, dstEleTy); - auto conv = builder.create(loc, dstEleTy, src); - builder.create(loc, conv, addr); + auto conv = fir::ConvertOp::create(builder, loc, dstEleTy, src); + fir::StoreOp::create(builder, loc, conv, addr); srcTy = dstEleTy; } else { // Put constant in memory if it is not. addr = builder.createTemporary(loc, srcTy); - builder.create(loc, src, addr); + fir::StoreOp::create(builder, loc, src, addr); } } } else { @@ -582,7 +585,7 @@ static mlir::Value emboxSrc(mlir::PatternRewriter &rewriter, /*slice=*/nullptr, lenParams, /*tdesc=*/nullptr); mlir::Value src = builder.createTemporary(loc, box.getType()); - builder.create(loc, box, src); + fir::StoreOp::create(builder, loc, box, src); return src; } @@ -601,7 +604,7 @@ static mlir::Value emboxDst(mlir::PatternRewriter &rewriter, /*slice=*/nullptr, lenParams, /*tdesc=*/nullptr); mlir::Value dst = builder.createTemporary(loc, dstBox.getType()); - builder.create(loc, dstBox, dst); + fir::StoreOp::create(builder, loc, dstBox, dst); return dst; } @@ -660,7 +663,7 @@ struct CUFDataTransferOpConversion fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); llvm::SmallVector args{fir::runtime::createArguments( builder, loc, fTy, dst, src, modeValue, sourceFile, sourceLine)}; - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); rewriter.eraseOp(op); return mlir::success(); } @@ -679,12 +682,12 @@ struct CUFDataTransferOpConversion extents.push_back(i.value()); } - nbElement = rewriter.create(loc, i64Ty, extents[0]); + nbElement = fir::ConvertOp::create(rewriter, loc, i64Ty, extents[0]); for (unsigned i = 1; i < extents.size(); ++i) { auto operand = - rewriter.create(loc, i64Ty, extents[i]); + fir::ConvertOp::create(rewriter, loc, i64Ty, extents[i]); nbElement = - rewriter.create(loc, nbElement, operand); + mlir::arith::MulIOp::create(rewriter, loc, nbElement, operand); } } else { if (auto seqTy = mlir::dyn_cast_or_null(dstTy)) @@ -699,12 +702,11 @@ struct CUFDataTransferOpConversion } else { width = computeWidth(loc, dstTy, kindMap); } - mlir::Value widthValue = rewriter.create( - loc, i64Ty, rewriter.getIntegerAttr(i64Ty, width)); - mlir::Value bytes = - nbElement - ? rewriter.create(loc, nbElement, widthValue) - : widthValue; + mlir::Value widthValue = mlir::arith::ConstantOp::create( + rewriter, loc, i64Ty, rewriter.getIntegerAttr(i64Ty, width)); + mlir::Value bytes = nbElement ? mlir::arith::MulIOp::create( + rewriter, loc, nbElement, widthValue) + : widthValue; mlir::func::FuncOp func = fir::runtime::getRuntimeFunc(loc, @@ -719,13 +721,13 @@ struct CUFDataTransferOpConversion // Materialize the src if constant. if (matchPattern(src.getDefiningOp(), mlir::m_Constant())) { mlir::Value temp = builder.createTemporary(loc, srcTy); - builder.create(loc, src, temp); + fir::StoreOp::create(builder, loc, src, temp); src = temp; } llvm::SmallVector args{ fir::runtime::createArguments(builder, loc, fTy, dst, src, bytes, modeValue, sourceFile, sourceLine)}; - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); rewriter.eraseOp(op); return mlir::success(); } @@ -734,7 +736,7 @@ struct CUFDataTransferOpConversion 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); + fir::StoreOp::create(builder, loc, val, box); return box; } return val; @@ -768,7 +770,7 @@ struct CUFDataTransferOpConversion fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); llvm::SmallVector args{fir::runtime::createArguments( builder, loc, fTy, dst, src, modeValue, sourceFile, sourceLine)}; - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); rewriter.eraseOp(op); } else { // Transfer from a descriptor. @@ -784,7 +786,7 @@ struct CUFDataTransferOpConversion fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); llvm::SmallVector args{fir::runtime::createArguments( builder, loc, fTy, dst, src, modeValue, sourceFile, sourceLine)}; - builder.create(loc, func, args); + fir::CallOp::create(builder, loc, func, args); rewriter.eraseOp(op); } return mlir::success(); @@ -810,20 +812,21 @@ struct CUFLaunchOpConversion mlir::PatternRewriter &rewriter) const override { mlir::Location loc = op.getLoc(); auto idxTy = mlir::IndexType::get(op.getContext()); - mlir::Value zero = rewriter.create( - loc, rewriter.getIntegerType(32), rewriter.getI32IntegerAttr(0)); + mlir::Value zero = mlir::arith::ConstantOp::create( + rewriter, loc, rewriter.getIntegerType(32), + rewriter.getI32IntegerAttr(0)); auto gridSizeX = - rewriter.create(loc, idxTy, op.getGridX()); + mlir::arith::IndexCastOp::create(rewriter, loc, idxTy, op.getGridX()); auto gridSizeY = - rewriter.create(loc, idxTy, op.getGridY()); + mlir::arith::IndexCastOp::create(rewriter, loc, idxTy, op.getGridY()); auto gridSizeZ = - rewriter.create(loc, idxTy, op.getGridZ()); + mlir::arith::IndexCastOp::create(rewriter, loc, idxTy, op.getGridZ()); auto blockSizeX = - rewriter.create(loc, idxTy, op.getBlockX()); + mlir::arith::IndexCastOp::create(rewriter, loc, idxTy, op.getBlockX()); auto blockSizeY = - rewriter.create(loc, idxTy, op.getBlockY()); + mlir::arith::IndexCastOp::create(rewriter, loc, idxTy, op.getBlockY()); auto blockSizeZ = - rewriter.create(loc, idxTy, op.getBlockZ()); + mlir::arith::IndexCastOp::create(rewriter, loc, idxTy, op.getBlockZ()); auto kernelName = mlir::SymbolRefAttr::get( rewriter.getStringAttr(cudaDeviceModuleName), {mlir::SymbolRefAttr::get( @@ -835,12 +838,12 @@ struct CUFLaunchOpConversion op.getCallee().getLeafReference())) { if (auto clusterDimsAttr = funcOp->getAttrOfType( cuf::getClusterDimsAttrName())) { - clusterDimX = rewriter.create( - loc, clusterDimsAttr.getX().getInt()); - clusterDimY = rewriter.create( - loc, clusterDimsAttr.getY().getInt()); - clusterDimZ = rewriter.create( - loc, clusterDimsAttr.getZ().getInt()); + clusterDimX = mlir::arith::ConstantIndexOp::create( + rewriter, loc, clusterDimsAttr.getX().getInt()); + clusterDimY = mlir::arith::ConstantIndexOp::create( + rewriter, loc, clusterDimsAttr.getY().getInt()); + clusterDimZ = mlir::arith::ConstantIndexOp::create( + rewriter, loc, clusterDimsAttr.getZ().getInt()); } procAttr = funcOp->getAttrOfType(cuf::getProcAttrName()); @@ -870,8 +873,9 @@ struct CUFLaunchOpConversion args.push_back(arg); } mlir::Value dynamicShmemSize = op.getBytes() ? op.getBytes() : zero; - auto gpuLaunchOp = rewriter.create( - loc, kernelName, mlir::gpu::KernelDim3{gridSizeX, gridSizeY, gridSizeZ}, + auto gpuLaunchOp = mlir::gpu::LaunchFuncOp::create( + rewriter, loc, kernelName, + mlir::gpu::KernelDim3{gridSizeX, gridSizeY, gridSizeZ}, mlir::gpu::KernelDim3{blockSizeX, blockSizeY, blockSizeZ}, dynamicShmemSize, args); if (clusterDimX && clusterDimY && clusterDimZ) { @@ -883,7 +887,7 @@ struct CUFLaunchOpConversion mlir::OpBuilder::InsertionGuard guard(rewriter); rewriter.setInsertionPoint(gpuLaunchOp); mlir::Value stream = - rewriter.create(loc, op.getStream()); + cuf::StreamCastOp::create(rewriter, loc, op.getStream()); gpuLaunchOp.getAsyncDependenciesMutable().append(stream); } if (procAttr) @@ -916,8 +920,9 @@ struct CUFSyncDescriptorOpConversion if (!globalOp) return mlir::failure(); - auto hostAddr = builder.create( - loc, fir::ReferenceType::get(globalOp.getType()), op.getGlobalName()); + auto hostAddr = fir::AddrOfOp::create( + builder, loc, fir::ReferenceType::get(globalOp.getType()), + op.getGlobalName()); fir::runtime::cuda::genSyncGlobalDescriptor(builder, loc, hostAddr); op.erase(); return mlir::success(); diff --git a/flang/lib/Optimizer/Transforms/CharacterConversion.cpp b/flang/lib/Optimizer/Transforms/CharacterConversion.cpp index aee7e8ca5cb66..13da38e92c234 100644 --- a/flang/lib/Optimizer/Transforms/CharacterConversion.cpp +++ b/flang/lib/Optimizer/Transforms/CharacterConversion.cpp @@ -48,12 +48,13 @@ class CharacterConvertConversion << "running character conversion on " << conv << '\n'); // Establish a loop that executes count iterations. - auto zero = rewriter.create(loc, 0); - auto one = rewriter.create(loc, 1); + auto zero = mlir::arith::ConstantIndexOp::create(rewriter, loc, 0); + auto one = mlir::arith::ConstantIndexOp::create(rewriter, loc, 1); auto idxTy = rewriter.getIndexType(); - auto castCnt = rewriter.create(loc, idxTy, conv.getCount()); - auto countm1 = rewriter.create(loc, castCnt, one); - auto loop = rewriter.create(loc, zero, countm1, one); + auto castCnt = + fir::ConvertOp::create(rewriter, loc, idxTy, conv.getCount()); + auto countm1 = mlir::arith::SubIOp::create(rewriter, loc, castCnt, one); + auto loop = fir::DoLoopOp::create(rewriter, loc, zero, countm1, one); auto insPt = rewriter.saveInsertionPoint(); rewriter.setInsertionPointToStart(loop.getBody()); @@ -75,21 +76,22 @@ class CharacterConvertConversion auto toTy = rewriter.getIntegerType(toBits); auto toPtrTy = pointerType(toBits); auto fromPtr = - rewriter.create(loc, fromPtrTy, conv.getFrom()); - auto toPtr = rewriter.create(loc, toPtrTy, conv.getTo()); + fir::ConvertOp::create(rewriter, loc, fromPtrTy, conv.getFrom()); + auto toPtr = fir::ConvertOp::create(rewriter, loc, toPtrTy, conv.getTo()); auto getEleTy = [&](unsigned bits) { return fir::ReferenceType::get(rewriter.getIntegerType(bits)); }; - auto fromi = rewriter.create( - loc, getEleTy(fromBits), fromPtr, - mlir::ValueRange{loop.getInductionVar()}); - auto toi = rewriter.create( - loc, getEleTy(toBits), toPtr, mlir::ValueRange{loop.getInductionVar()}); - auto load = rewriter.create(loc, fromi); + auto fromi = + fir::CoordinateOp::create(rewriter, loc, getEleTy(fromBits), fromPtr, + mlir::ValueRange{loop.getInductionVar()}); + auto toi = + fir::CoordinateOp::create(rewriter, loc, getEleTy(toBits), toPtr, + mlir::ValueRange{loop.getInductionVar()}); + auto load = fir::LoadOp::create(rewriter, loc, fromi); mlir::Value icast = (fromBits >= toBits) - ? rewriter.create(loc, toTy, load).getResult() - : rewriter.create(loc, toTy, load) + ? fir::ConvertOp::create(rewriter, loc, toTy, load).getResult() + : mlir::arith::ExtUIOp::create(rewriter, loc, toTy, load) .getResult(); rewriter.replaceOpWithNewOp(conv, icast, toi); rewriter.restoreInsertionPoint(insPt); diff --git a/flang/lib/Optimizer/Transforms/ConstantArgumentGlobalisation.cpp b/flang/lib/Optimizer/Transforms/ConstantArgumentGlobalisation.cpp index 239a7cdaa4cf2..afafbd8179aff 100644 --- a/flang/lib/Optimizer/Transforms/ConstantArgumentGlobalisation.cpp +++ b/flang/lib/Optimizer/Transforms/ConstantArgumentGlobalisation.cpp @@ -111,11 +111,11 @@ class CallOpRewriter : public mlir::OpRewritePattern { builder.insert(cln); mlir::Value val = builder.createConvert(loc, varTy, cln->getResult(0)); - builder.create(loc, val); + fir::HasValueOp::create(builder, loc, val); }, builder.createInternalLinkage()); - mlir::Value addr = builder.create(loc, global.resultType(), - global.getSymbol()); + mlir::Value addr = fir::AddrOfOp::create( + builder, loc, global.resultType(), global.getSymbol()); newOperands.push_back(addr); needUpdate = true; } @@ -125,11 +125,11 @@ class CallOpRewriter : public mlir::OpRewritePattern { llvm::SmallVector newResultTypes; newResultTypes.append(callOp.getResultTypes().begin(), callOp.getResultTypes().end()); - fir::CallOp newOp = builder.create( - loc, - callOp.getCallee().has_value() ? callOp.getCallee().value() - : mlir::SymbolRefAttr{}, - newResultTypes, newOperands); + fir::CallOp newOp = fir::CallOp::create(builder, loc, + callOp.getCallee().has_value() + ? callOp.getCallee().value() + : mlir::SymbolRefAttr{}, + newResultTypes, newOperands); // Copy all the attributes from the old to new op. newOp->setAttrs(callOp->getAttrs()); rewriter.replaceOp(callOp, newOp); diff --git a/flang/lib/Optimizer/Transforms/ControlFlowConverter.cpp b/flang/lib/Optimizer/Transforms/ControlFlowConverter.cpp index 3d35803e6a2d3..e466aed753e63 100644 --- a/flang/lib/Optimizer/Transforms/ControlFlowConverter.cpp +++ b/flang/lib/Optimizer/Transforms/ControlFlowConverter.cpp @@ -83,17 +83,17 @@ class CfgLoopConv : public mlir::OpRewritePattern { // Initalization block rewriter.setInsertionPointToEnd(initBlock); - auto diff = rewriter.create(loc, high, low); - auto distance = rewriter.create(loc, diff, step); + auto diff = mlir::arith::SubIOp::create(rewriter, loc, high, low); + auto distance = mlir::arith::AddIOp::create(rewriter, loc, diff, step); mlir::Value iters = - rewriter.create(loc, distance, step); + mlir::arith::DivSIOp::create(rewriter, loc, distance, step); if (forceLoopToExecuteOnce) { - auto zero = rewriter.create(loc, 0); - auto cond = rewriter.create( - loc, arith::CmpIPredicate::sle, iters, zero); - auto one = rewriter.create(loc, 1); - iters = rewriter.create(loc, cond, one, iters); + auto zero = mlir::arith::ConstantIndexOp::create(rewriter, loc, 0); + auto cond = mlir::arith::CmpIOp::create( + rewriter, loc, arith::CmpIPredicate::sle, iters, zero); + auto one = mlir::arith::ConstantIndexOp::create(rewriter, loc, 1); + iters = mlir::arith::SelectOp::create(rewriter, loc, cond, one, iters); } llvm::SmallVector loopOperands; @@ -102,20 +102,20 @@ class CfgLoopConv : public mlir::OpRewritePattern { loopOperands.append(operands.begin(), operands.end()); loopOperands.push_back(iters); - rewriter.create(loc, conditionalBlock, loopOperands); + mlir::cf::BranchOp::create(rewriter, loc, conditionalBlock, loopOperands); // Last loop block auto *terminator = lastBlock->getTerminator(); rewriter.setInsertionPointToEnd(lastBlock); auto iv = conditionalBlock->getArgument(0); mlir::Value steppedIndex = - rewriter.create(loc, iv, step, iofAttr); + mlir::arith::AddIOp::create(rewriter, loc, iv, step, iofAttr); assert(steppedIndex && "must be a Value"); auto lastArg = conditionalBlock->getNumArguments() - 1; auto itersLeft = conditionalBlock->getArgument(lastArg); - auto one = rewriter.create(loc, 1); + auto one = mlir::arith::ConstantIndexOp::create(rewriter, loc, 1); mlir::Value itersMinusOne = - rewriter.create(loc, itersLeft, one); + mlir::arith::SubIOp::create(rewriter, loc, itersLeft, one); llvm::SmallVector loopCarried; loopCarried.push_back(steppedIndex); @@ -123,8 +123,8 @@ class CfgLoopConv : public mlir::OpRewritePattern { : terminator->operand_begin(); loopCarried.append(begin, terminator->operand_end()); loopCarried.push_back(itersMinusOne); - auto backEdge = - rewriter.create(loc, conditionalBlock, loopCarried); + auto backEdge = mlir::cf::BranchOp::create(rewriter, loc, conditionalBlock, + loopCarried); rewriter.eraseOp(terminator); // Copy loop annotations from the do loop to the loop back edge. @@ -133,13 +133,13 @@ class CfgLoopConv : public mlir::OpRewritePattern { // Conditional block rewriter.setInsertionPointToEnd(conditionalBlock); - auto zero = rewriter.create(loc, 0); - auto comparison = rewriter.create( - loc, arith::CmpIPredicate::sgt, itersLeft, zero); + auto zero = mlir::arith::ConstantIndexOp::create(rewriter, loc, 0); + auto comparison = mlir::arith::CmpIOp::create( + rewriter, loc, arith::CmpIPredicate::sgt, itersLeft, zero); - rewriter.create( - loc, comparison, firstBlock, llvm::ArrayRef(), endBlock, - llvm::ArrayRef()); + mlir::cf::CondBranchOp::create(rewriter, loc, comparison, firstBlock, + llvm::ArrayRef(), endBlock, + llvm::ArrayRef()); // The result of the loop operation is the values of the condition block // arguments except the induction variable on the last iteration. @@ -180,7 +180,7 @@ class CfgIfConv : public mlir::OpRewritePattern { continueBlock = rewriter.createBlock( remainingOpsBlock, ifOp.getResultTypes(), llvm::SmallVector(ifOp.getNumResults(), loc)); - rewriter.create(loc, remainingOpsBlock); + mlir::cf::BranchOp::create(rewriter, loc, remainingOpsBlock); } // Move blocks from the "then" region to the region containing 'fir.if', @@ -190,8 +190,8 @@ class CfgIfConv : public mlir::OpRewritePattern { auto *ifOpTerminator = ifOpRegion.back().getTerminator(); auto ifOpTerminatorOperands = ifOpTerminator->getOperands(); rewriter.setInsertionPointToEnd(&ifOpRegion.back()); - rewriter.create(loc, continueBlock, - ifOpTerminatorOperands); + mlir::cf::BranchOp::create(rewriter, loc, continueBlock, + ifOpTerminatorOperands); rewriter.eraseOp(ifOpTerminator); rewriter.inlineRegionBefore(ifOpRegion, continueBlock); @@ -205,16 +205,17 @@ class CfgIfConv : public mlir::OpRewritePattern { auto *otherwiseTerm = otherwiseRegion.back().getTerminator(); auto otherwiseTermOperands = otherwiseTerm->getOperands(); rewriter.setInsertionPointToEnd(&otherwiseRegion.back()); - rewriter.create(loc, continueBlock, - otherwiseTermOperands); + mlir::cf::BranchOp::create(rewriter, loc, continueBlock, + otherwiseTermOperands); rewriter.eraseOp(otherwiseTerm); rewriter.inlineRegionBefore(otherwiseRegion, continueBlock); } rewriter.setInsertionPointToEnd(condBlock); - auto branchOp = rewriter.create( - loc, ifOp.getCondition(), ifOpBlock, llvm::ArrayRef(), - otherwiseBlock, llvm::ArrayRef()); + auto branchOp = mlir::cf::CondBranchOp::create( + rewriter, loc, ifOp.getCondition(), ifOpBlock, + llvm::ArrayRef(), otherwiseBlock, + llvm::ArrayRef()); llvm::ArrayRef weights = ifOp.getWeights(); if (!weights.empty()) branchOp.setWeights(weights); @@ -269,7 +270,7 @@ class CfgIterWhileConv : public mlir::OpRewritePattern { rewriter.setInsertionPointToEnd(lastBodyBlock); auto step = whileOp.getStep(); mlir::Value stepped = - rewriter.create(loc, iv, step, iofAttr); + mlir::arith::AddIOp::create(rewriter, loc, iv, step, iofAttr); assert(stepped && "must be a Value"); llvm::SmallVector loopCarried; @@ -278,7 +279,7 @@ class CfgIterWhileConv : public mlir::OpRewritePattern { ? std::next(terminator->operand_begin()) : terminator->operand_begin(); loopCarried.append(begin, terminator->operand_end()); - rewriter.create(loc, conditionBlock, loopCarried); + mlir::cf::BranchOp::create(rewriter, loc, conditionBlock, loopCarried); rewriter.eraseOp(terminator); // Compute loop bounds before branching to the condition. @@ -293,31 +294,31 @@ class CfgIterWhileConv : public mlir::OpRewritePattern { destOperands.push_back(lowerBound); auto iterOperands = whileOp.getIterOperands(); destOperands.append(iterOperands.begin(), iterOperands.end()); - rewriter.create(loc, conditionBlock, destOperands); + mlir::cf::BranchOp::create(rewriter, loc, conditionBlock, destOperands); // With the body block done, we can fill in the condition block. rewriter.setInsertionPointToEnd(conditionBlock); // The comparison depends on the sign of the step value. We fully expect // this expression to be folded by the optimizer or LLVM. This expression // is written this way so that `step == 0` always returns `false`. - auto zero = rewriter.create(loc, 0); - auto compl0 = rewriter.create( - loc, arith::CmpIPredicate::slt, zero, step); - auto compl1 = rewriter.create( - loc, arith::CmpIPredicate::sle, iv, upperBound); - auto compl2 = rewriter.create( - loc, arith::CmpIPredicate::slt, step, zero); - auto compl3 = rewriter.create( - loc, arith::CmpIPredicate::sle, upperBound, iv); - auto cmp0 = rewriter.create(loc, compl0, compl1); - auto cmp1 = rewriter.create(loc, compl2, compl3); - auto cmp2 = rewriter.create(loc, cmp0, cmp1); + auto zero = mlir::arith::ConstantIndexOp::create(rewriter, loc, 0); + auto compl0 = mlir::arith::CmpIOp::create( + rewriter, loc, arith::CmpIPredicate::slt, zero, step); + auto compl1 = mlir::arith::CmpIOp::create( + rewriter, loc, arith::CmpIPredicate::sle, iv, upperBound); + auto compl2 = mlir::arith::CmpIOp::create( + rewriter, loc, arith::CmpIPredicate::slt, step, zero); + auto compl3 = mlir::arith::CmpIOp::create( + rewriter, loc, arith::CmpIPredicate::sle, upperBound, iv); + auto cmp0 = mlir::arith::AndIOp::create(rewriter, loc, compl0, compl1); + auto cmp1 = mlir::arith::AndIOp::create(rewriter, loc, compl2, compl3); + auto cmp2 = mlir::arith::OrIOp::create(rewriter, loc, cmp0, cmp1); // Remember to AND in the early-exit bool. auto comparison = - rewriter.create(loc, iterateVar, cmp2); - rewriter.create( - loc, comparison, firstBodyBlock, llvm::ArrayRef(), - endBlock, llvm::ArrayRef()); + mlir::arith::AndIOp::create(rewriter, loc, iterateVar, cmp2); + mlir::cf::CondBranchOp::create(rewriter, loc, comparison, firstBodyBlock, + llvm::ArrayRef(), endBlock, + llvm::ArrayRef()); // The result of the loop operation is the values of the condition block // arguments except the induction variable on the last iteration. auto args = whileOp.getFinalValue() diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp index abad500d3f657..5dcb54eaf9b9d 100644 --- a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp +++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp @@ -103,13 +103,14 @@ mlir::LLVM::DILocalVariableAttr DebugTypeGenerator::generateArtificialVariable( mlir::Type type = val.getType(); if (!mlir::isa(type) || !type.isSignlessInteger()) { type = builder.getIntegerType(64); - val = builder.create(declOp.getLoc(), type, val); + val = fir::ConvertOp::create(builder, declOp.getLoc(), type, val); } mlir::LLVM::DITypeAttr Ty = convertType(type, fileAttr, scope, declOp); auto lvAttr = mlir::LLVM::DILocalVariableAttr::get( context, scope, name, fileAttr, /*line=*/0, /*argNo=*/0, /*alignInBits=*/0, Ty, mlir::LLVM::DIFlags::Artificial); - builder.create(declOp.getLoc(), val, lvAttr, nullptr); + mlir::LLVM::DbgValueOp::create(builder, declOp.getLoc(), val, lvAttr, + nullptr); return lvAttr; } diff --git a/flang/lib/Optimizer/Transforms/FIRToSCF.cpp b/flang/lib/Optimizer/Transforms/FIRToSCF.cpp index f06ad2db90d55..d7d1865bc56ba 100644 --- a/flang/lib/Optimizer/Transforms/FIRToSCF.cpp +++ b/flang/lib/Optimizer/Transforms/FIRToSCF.cpp @@ -49,13 +49,13 @@ struct DoLoopConversion : public OpRewritePattern { // must be a positive value. // For easier conversion, we calculate the trip count and use a canonical // induction variable. - auto diff = rewriter.create(loc, high, low); - auto distance = rewriter.create(loc, diff, step); - auto tripCount = rewriter.create(loc, distance, step); - auto zero = rewriter.create(loc, 0); - auto one = rewriter.create(loc, 1); + auto diff = arith::SubIOp::create(rewriter, loc, high, low); + auto distance = arith::AddIOp::create(rewriter, loc, diff, step); + auto tripCount = arith::DivSIOp::create(rewriter, loc, distance, step); + auto zero = arith::ConstantIndexOp::create(rewriter, loc, 0); + auto one = arith::ConstantIndexOp::create(rewriter, loc, 1); auto scfForOp = - rewriter.create(loc, zero, tripCount, one, iterArgs); + scf::ForOp::create(rewriter, loc, zero, tripCount, one, iterArgs); auto &loopOps = doLoopOp.getBody()->getOperations(); auto resultOp = cast(doLoopOp.getBody()->getTerminator()); @@ -68,12 +68,12 @@ struct DoLoopConversion : public OpRewritePattern { rewriter.setInsertionPointToStart(loweredBody); Value iv = - rewriter.create(loc, scfForOp.getInductionVar(), step); - iv = rewriter.create(loc, low, iv); + arith::MulIOp::create(rewriter, loc, scfForOp.getInductionVar(), step); + iv = arith::AddIOp::create(rewriter, loc, low, iv); if (!results.empty()) { rewriter.setInsertionPointToEnd(loweredBody); - rewriter.create(resultOp->getLoc(), results); + scf::YieldOp::create(rewriter, resultOp->getLoc(), results); } doLoopOp.getInductionVar().replaceAllUsesWith(iv); rewriter.replaceAllUsesWith(doLoopOp.getRegionIterArgs(), diff --git a/flang/lib/Optimizer/Transforms/GenRuntimeCallsForTest.cpp b/flang/lib/Optimizer/Transforms/GenRuntimeCallsForTest.cpp index 7ea3b9c670c69..699be12178881 100644 --- a/flang/lib/Optimizer/Transforms/GenRuntimeCallsForTest.cpp +++ b/flang/lib/Optimizer/Transforms/GenRuntimeCallsForTest.cpp @@ -91,8 +91,8 @@ void GenRuntimeCallsForTestPass::runOnOperation() { // Generate the wrapper function body that consists of a call and return. builder.setInsertionPointToStart(callerFunc.addEntryBlock()); mlir::Block::BlockArgListType args = callerFunc.front().getArguments(); - auto callOp = builder.create(loc, funcOp, args); - builder.create(loc, callOp.getResults()); + auto callOp = fir::CallOp::create(builder, loc, funcOp, args); + mlir::func::ReturnOp::create(builder, loc, callOp.getResults()); newFuncs.push_back(callerFunc.getOperation()); builder.restoreInsertionPoint(insertPt); diff --git a/flang/lib/Optimizer/Transforms/LoopVersioning.cpp b/flang/lib/Optimizer/Transforms/LoopVersioning.cpp index 056bdf63d914f..0095159398155 100644 --- a/flang/lib/Optimizer/Transforms/LoopVersioning.cpp +++ b/flang/lib/Optimizer/Transforms/LoopVersioning.cpp @@ -285,7 +285,7 @@ static mlir::Value getIndex(fir::FirOpBuilder &builder, mlir::Operation *op, // index_0 = index - lb; if (lb.getType() != index.getType()) lb = builder.createConvert(coop.getLoc(), index.getType(), lb); - return builder.create(coop.getLoc(), index, lb); + return mlir::arith::SubIOp::create(builder, coop.getLoc(), index, lb); } void LoopVersioningPass::runOnOperation() { @@ -483,26 +483,26 @@ void LoopVersioningPass::runOnOperation() { unsigned ndims = arg.rank; for (unsigned i = 0; i < ndims; i++) { mlir::Value dimIdx = builder.createIntegerConstant(loc, idxTy, i); - arg.dims[i] = builder.create(loc, idxTy, idxTy, idxTy, - arg.arg, dimIdx); + arg.dims[i] = fir::BoxDimsOp::create(builder, loc, idxTy, idxTy, idxTy, + arg.arg, dimIdx); } // We only care about lowest order dimension, here. mlir::Value elemSize = builder.createIntegerConstant(loc, idxTy, arg.size); - mlir::Value cmp = builder.create( - loc, mlir::arith::CmpIPredicate::eq, arg.dims[0].getResult(2), - elemSize); + mlir::Value cmp = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, + arg.dims[0].getResult(2), elemSize); if (!allCompares) { allCompares = cmp; } else { allCompares = - builder.create(loc, cmp, allCompares); + mlir::arith::AndIOp::create(builder, loc, cmp, allCompares); } } auto ifOp = - builder.create(loc, op.op->getResultTypes(), allCompares, - /*withElse=*/true); + fir::IfOp::create(builder, loc, op.op->getResultTypes(), allCompares, + /*withElse=*/true); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); LLVM_DEBUG(llvm::dbgs() << "Creating cloned loop\n"); @@ -515,8 +515,8 @@ void LoopVersioningPass::runOnOperation() { mlir::Type arrTy = fir::SequenceType::get(newShape, elementType); mlir::Type boxArrTy = fir::BoxType::get(arrTy); mlir::Type refArrTy = builder.getRefType(arrTy); - auto carg = builder.create(loc, boxArrTy, arg.arg); - auto caddr = builder.create(loc, refArrTy, carg); + auto carg = fir::ConvertOp::create(builder, loc, boxArrTy, arg.arg); + auto caddr = fir::BoxAddrOp::create(builder, loc, refArrTy, carg); auto insPt = builder.saveInsertionPoint(); // Use caddr instead of arg. clonedLoop->walk([&](mlir::Operation *coop) { @@ -540,9 +540,9 @@ void LoopVersioningPass::runOnOperation() { mlir::Value scale = builder.createConvert(loc, idxTy, arg.dims[i].getResult(2)); curIndex = - builder.create(loc, scale, curIndex); - totalIndex = (totalIndex) ? builder.create( - loc, curIndex, totalIndex) + mlir::arith::MulIOp::create(builder, loc, scale, curIndex); + totalIndex = (totalIndex) ? mlir::arith::AddIOp::create( + builder, loc, curIndex, totalIndex) : curIndex; } // This is the lowest dimension - which doesn't need scaling @@ -554,16 +554,16 @@ void LoopVersioningPass::runOnOperation() { unsigned bits = llvm::Log2_32(arg.size); mlir::Value elemShift = builder.createIntegerConstant(loc, idxTy, bits); - totalIndex = builder.create( - loc, - builder.create(loc, totalIndex, - elemShift), + totalIndex = mlir::arith::AddIOp::create( + builder, loc, + mlir::arith::ShRSIOp::create(builder, loc, totalIndex, + elemShift), finalIndex); } else { totalIndex = finalIndex; } - auto newOp = builder.create( - loc, builder.getRefType(elementType), caddr, + auto newOp = fir::CoordinateOp::create( + builder, loc, builder.getRefType(elementType), caddr, mlir::ValueRange{totalIndex}); LLVM_DEBUG(newOp->dump()); coop->getResult(0).replaceAllUsesWith(newOp->getResult(0)); @@ -582,7 +582,7 @@ void LoopVersioningPass::runOnOperation() { mlir::ResultRange results = clonedLoop->getResults(); bool hasResults = (results.size() > 0); if (hasResults) - builder.create(loc, results); + fir::ResultOp::create(builder, loc, results); // Add the original loop in the else-side of the if operation. builder.setInsertionPointToStart(&ifOp.getElseRegion().front()); @@ -591,7 +591,7 @@ void LoopVersioningPass::runOnOperation() { builder.insert(op.op); // Rely on "cloned loop has results, so original loop also has results". if (hasResults) { - builder.create(loc, op.op->getResults()); + fir::ResultOp::create(builder, loc, op.op->getResults()); } else { // Use an assert to check this. assert(op.op->getResults().size() == 0 && diff --git a/flang/lib/Optimizer/Transforms/MemoryAllocation.cpp b/flang/lib/Optimizer/Transforms/MemoryAllocation.cpp index 3f308a8f4b560..99040898728bb 100644 --- a/flang/lib/Optimizer/Transforms/MemoryAllocation.cpp +++ b/flang/lib/Optimizer/Transforms/MemoryAllocation.cpp @@ -68,9 +68,9 @@ static mlir::Value genAllocmem(mlir::OpBuilder &builder, fir::AllocaOp alloca, }; llvm::StringRef uniqName = unpackName(alloca.getUniqName()); llvm::StringRef bindcName = unpackName(alloca.getBindcName()); - auto heap = builder.create(alloca.getLoc(), varTy, uniqName, - bindcName, alloca.getTypeparams(), - alloca.getShape()); + auto heap = fir::AllocMemOp::create(builder, alloca.getLoc(), varTy, uniqName, + bindcName, alloca.getTypeparams(), + alloca.getShape()); LLVM_DEBUG(llvm::dbgs() << "memory allocation opt: replaced " << alloca << " with " << heap << '\n'); return heap; @@ -78,7 +78,7 @@ static mlir::Value genAllocmem(mlir::OpBuilder &builder, fir::AllocaOp alloca, static void genFreemem(mlir::Location loc, mlir::OpBuilder &builder, mlir::Value allocmem) { - [[maybe_unused]] auto free = builder.create(loc, allocmem); + [[maybe_unused]] auto free = fir::FreeMemOp::create(builder, loc, allocmem); LLVM_DEBUG(llvm::dbgs() << "memory allocation opt: add free " << free << " for " << allocmem << '\n'); } diff --git a/flang/lib/Optimizer/Transforms/MemoryUtils.cpp b/flang/lib/Optimizer/Transforms/MemoryUtils.cpp index 1f8edf851de9b..789111cd35f67 100644 --- a/flang/lib/Optimizer/Transforms/MemoryUtils.cpp +++ b/flang/lib/Optimizer/Transforms/MemoryUtils.cpp @@ -200,30 +200,30 @@ void AllocaReplaceImpl::genIndirectDeallocation( // and access it indirectly in the entry points that do not dominate. rewriter.setInsertionPointToStart(&owningRegion.front()); mlir::Type heapType = fir::HeapType::get(alloca.getInType()); - mlir::Value ptrVar = rewriter.create(loc, heapType); - mlir::Value nullPtr = rewriter.create(loc, heapType); - rewriter.create(loc, nullPtr, ptrVar); + mlir::Value ptrVar = fir::AllocaOp::create(rewriter, loc, heapType); + mlir::Value nullPtr = fir::ZeroOp::create(rewriter, loc, heapType); + fir::StoreOp::create(rewriter, loc, nullPtr, ptrVar); // TODO: introducing a pointer compare op in FIR would help // generating less IR here. mlir::Type intPtrTy = fir::getIntPtrType(rewriter); - mlir::Value c0 = rewriter.create( - loc, intPtrTy, rewriter.getIntegerAttr(intPtrTy, 0)); + mlir::Value c0 = mlir::arith::ConstantOp::create( + rewriter, loc, intPtrTy, rewriter.getIntegerAttr(intPtrTy, 0)); // Store new storage address right after its creation. rewriter.restoreInsertionPoint(replacementInsertPoint); mlir::Value castReplacement = fir::factory::createConvert(rewriter, loc, heapType, replacement); - rewriter.create(loc, castReplacement, ptrVar); + fir::StoreOp::create(rewriter, loc, castReplacement, ptrVar); // Generate conditional deallocation at every deallocation point. auto genConditionalDealloc = [&](mlir::Location loc) { - mlir::Value ptrVal = rewriter.create(loc, ptrVar); + mlir::Value ptrVal = fir::LoadOp::create(rewriter, loc, ptrVar); mlir::Value ptrToInt = - rewriter.create(loc, intPtrTy, ptrVal); - mlir::Value isAllocated = rewriter.create( - loc, mlir::arith::CmpIPredicate::ne, ptrToInt, c0); - auto ifOp = rewriter.create(loc, std::nullopt, isAllocated, - /*withElseRegion=*/false); + fir::ConvertOp::create(rewriter, loc, intPtrTy, ptrVal); + mlir::Value isAllocated = mlir::arith::CmpIOp::create( + rewriter, loc, mlir::arith::CmpIPredicate::ne, ptrToInt, c0); + auto ifOp = fir::IfOp::create(rewriter, loc, mlir::TypeRange{}, isAllocated, + /*withElseRegion=*/false); rewriter.setInsertionPointToStart(&ifOp.getThenRegion().front()); mlir::Value cast = fir::factory::createConvert( rewriter, loc, replacement.getType(), ptrVal); diff --git a/flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp b/flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp index 57eae1ff052a2..2c6601dec6e16 100644 --- a/flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp +++ b/flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp @@ -183,49 +183,51 @@ struct DispatchOpConv : public OpConversionPattern { mlir::Type tdescType = fir::TypeDescType::get(mlir::NoneType::get(rewriter.getContext())); mlir::Value boxDesc = - rewriter.create(loc, tdescType, passedObject); - boxDesc = rewriter.create( - loc, fir::ReferenceType::get(typeDescTy), boxDesc); + fir::BoxTypeDescOp::create(rewriter, loc, tdescType, passedObject); + boxDesc = fir::ConvertOp::create( + rewriter, loc, fir::ReferenceType::get(typeDescTy), boxDesc); // Load the bindings descriptor. auto bindingsCompName = Fortran::semantics::bindingDescCompName; fir::RecordType typeDescRecTy = mlir::cast(typeDescTy); - mlir::Value field = rewriter.create( - loc, fieldTy, bindingsCompName, typeDescRecTy, mlir::ValueRange{}); + mlir::Value field = + fir::FieldIndexOp::create(rewriter, loc, fieldTy, bindingsCompName, + typeDescRecTy, mlir::ValueRange{}); mlir::Type coorTy = fir::ReferenceType::get(typeDescRecTy.getType(bindingsCompName)); mlir::Value bindingBoxAddr = - rewriter.create(loc, coorTy, boxDesc, field); - mlir::Value bindingBox = rewriter.create(loc, bindingBoxAddr); + fir::CoordinateOp::create(rewriter, loc, coorTy, boxDesc, field); + mlir::Value bindingBox = fir::LoadOp::create(rewriter, loc, bindingBoxAddr); // Load the correct binding. - mlir::Value bindings = rewriter.create(loc, bindingBox); + mlir::Value bindings = fir::BoxAddrOp::create(rewriter, loc, bindingBox); fir::RecordType bindingTy = fir::unwrapIfDerived( mlir::cast(bindingBox.getType())); mlir::Type bindingAddrTy = fir::ReferenceType::get(bindingTy); - mlir::Value bindingIdxVal = rewriter.create( - loc, rewriter.getIndexType(), rewriter.getIndexAttr(bindingIdx)); - mlir::Value bindingAddr = rewriter.create( - loc, bindingAddrTy, bindings, bindingIdxVal); + mlir::Value bindingIdxVal = + mlir::arith::ConstantOp::create(rewriter, loc, rewriter.getIndexType(), + rewriter.getIndexAttr(bindingIdx)); + mlir::Value bindingAddr = fir::CoordinateOp::create( + rewriter, loc, bindingAddrTy, bindings, bindingIdxVal); // Get the function pointer. auto procCompName = Fortran::semantics::procCompName; - mlir::Value procField = rewriter.create( - loc, fieldTy, procCompName, bindingTy, mlir::ValueRange{}); + mlir::Value procField = fir::FieldIndexOp::create( + rewriter, loc, fieldTy, procCompName, bindingTy, mlir::ValueRange{}); fir::RecordType procTy = mlir::cast(bindingTy.getType(procCompName)); mlir::Type procRefTy = fir::ReferenceType::get(procTy); - mlir::Value procRef = rewriter.create( - loc, procRefTy, bindingAddr, procField); + mlir::Value procRef = fir::CoordinateOp::create(rewriter, loc, procRefTy, + bindingAddr, procField); auto addressFieldName = Fortran::lower::builtin::cptrFieldName; - mlir::Value addressField = rewriter.create( - loc, fieldTy, addressFieldName, procTy, mlir::ValueRange{}); + mlir::Value addressField = fir::FieldIndexOp::create( + rewriter, loc, fieldTy, addressFieldName, procTy, mlir::ValueRange{}); mlir::Type addressTy = procTy.getType(addressFieldName); mlir::Type addressRefTy = fir::ReferenceType::get(addressTy); - mlir::Value addressRef = rewriter.create( - loc, addressRefTy, procRef, addressField); - mlir::Value address = rewriter.create(loc, addressRef); + mlir::Value addressRef = fir::CoordinateOp::create( + rewriter, loc, addressRefTy, procRef, addressField); + mlir::Value address = fir::LoadOp::create(rewriter, loc, addressRef); // Get the function type. llvm::SmallVector argTypes; @@ -237,7 +239,7 @@ struct DispatchOpConv : public OpConversionPattern { mlir::Type funTy = mlir::FunctionType::get(rewriter.getContext(), argTypes, resTypes); - mlir::Value funcPtr = rewriter.create(loc, funTy, address); + mlir::Value funcPtr = fir::ConvertOp::create(rewriter, loc, funTy, address); // Make the call. llvm::SmallVector args{funcPtr}; @@ -398,12 +400,13 @@ llvm::LogicalResult SelectTypeConv::genTypeLadderStep( if (code == 0) return mlir::emitError(loc) << "type code unavailable for " << a.getType(); - mlir::Value typeCode = rewriter.create( - loc, rewriter.getI8IntegerAttr(code)); - mlir::Value selectorTypeCode = rewriter.create( - loc, rewriter.getI8Type(), selector); - cmp = rewriter.create( - loc, mlir::arith::CmpIPredicate::eq, selectorTypeCode, typeCode); + mlir::Value typeCode = mlir::arith::ConstantOp::create( + rewriter, loc, rewriter.getI8IntegerAttr(code)); + mlir::Value selectorTypeCode = fir::BoxTypeCodeOp::create( + rewriter, loc, rewriter.getI8Type(), selector); + cmp = mlir::arith::CmpIOp::create(rewriter, loc, + mlir::arith::CmpIPredicate::eq, + selectorTypeCode, typeCode); } else { // Flang inline the kind parameter in the type descriptor so we can // directly check if the type descriptor addresses are identical for @@ -418,16 +421,16 @@ llvm::LogicalResult SelectTypeConv::genTypeLadderStep( } else if (auto a = mlir::dyn_cast(attr)) { // Retrieve the type descriptor from the type guard statement record type. assert(mlir::isa(a.getType()) && "expect fir.record type"); - mlir::Value typeDescAddr = - rewriter.create(loc, mlir::TypeAttr::get(a.getType())); + mlir::Value typeDescAddr = fir::TypeDescOp::create( + rewriter, loc, mlir::TypeAttr::get(a.getType())); mlir::Type refNoneType = ReferenceType::get(rewriter.getNoneType()); mlir::Value typeDesc = - rewriter.create(loc, refNoneType, typeDescAddr); + ConvertOp::create(rewriter, loc, refNoneType, typeDescAddr); // Prepare the selector descriptor for the runtime call. mlir::Type descNoneTy = fir::BoxType::get(rewriter.getNoneType()); mlir::Value descSelector = - rewriter.create(loc, descNoneTy, selector); + ConvertOp::create(rewriter, loc, descNoneTy, selector); // Generate runtime call. llvm::StringRef fctName = RTNAME_STRING(ClassIs); @@ -455,10 +458,10 @@ llvm::LogicalResult SelectTypeConv::genTypeLadderStep( rewriter.createBlock(dest->getParent(), mlir::Region::iterator(dest)); rewriter.setInsertionPointToEnd(thisBlock); if (destOps.has_value()) - rewriter.create(loc, cmp, dest, destOps.value(), - newBlock, std::nullopt); + mlir::cf::CondBranchOp::create(rewriter, loc, cmp, dest, destOps.value(), + newBlock, mlir::ValueRange{}); else - rewriter.create(loc, cmp, dest, newBlock); + mlir::cf::CondBranchOp::create(rewriter, loc, cmp, dest, newBlock); rewriter.setInsertionPointToEnd(newBlock); return mlir::success(); } @@ -470,16 +473,17 @@ SelectTypeConv::genTypeDescCompare(mlir::Location loc, mlir::Value selector, mlir::PatternRewriter &rewriter) const { assert(mlir::isa(ty) && "expect fir.record type"); mlir::Value typeDescAddr = - rewriter.create(loc, mlir::TypeAttr::get(ty)); - mlir::Value selectorTdescAddr = rewriter.create( - loc, typeDescAddr.getType(), selector); + fir::TypeDescOp::create(rewriter, loc, mlir::TypeAttr::get(ty)); + mlir::Value selectorTdescAddr = fir::BoxTypeDescOp::create( + rewriter, loc, typeDescAddr.getType(), selector); auto intPtrTy = rewriter.getIndexType(); auto typeDescInt = - rewriter.create(loc, intPtrTy, typeDescAddr); + fir::ConvertOp::create(rewriter, loc, intPtrTy, typeDescAddr); auto selectorTdescInt = - rewriter.create(loc, intPtrTy, selectorTdescAddr); - return rewriter.create( - loc, mlir::arith::CmpIPredicate::eq, typeDescInt, selectorTdescInt); + fir::ConvertOp::create(rewriter, loc, intPtrTy, selectorTdescAddr); + return mlir::arith::CmpIOp::create(rewriter, loc, + mlir::arith::CmpIPredicate::eq, + typeDescInt, selectorTdescInt); } llvm::SmallSet diff --git a/flang/lib/Optimizer/Transforms/SimplifyFIROperations.cpp b/flang/lib/Optimizer/Transforms/SimplifyFIROperations.cpp index 506c8e66dbdfa..c6aec96ceb5ae 100644 --- a/flang/lib/Optimizer/Transforms/SimplifyFIROperations.cpp +++ b/flang/lib/Optimizer/Transforms/SimplifyFIROperations.cpp @@ -88,18 +88,18 @@ mlir::LogicalResult IsContiguousBoxCoversion::matchAndRewrite( // The scalar cases are supposed to be optimized by the canonicalization. if (rank == 1 || (op.getInnermost() && rank > 0)) { mlir::Type idxTy = builder.getIndexType(); - auto eleSize = builder.create(loc, idxTy, box); + auto eleSize = fir::BoxEleSizeOp::create(builder, loc, idxTy, box); mlir::Value zero = fir::factory::createZeroValue(builder, loc, idxTy); auto dimInfo = - builder.create(loc, idxTy, idxTy, idxTy, box, zero); + fir::BoxDimsOp::create(builder, loc, idxTy, idxTy, idxTy, box, zero); mlir::Value stride = dimInfo.getByteStride(); - mlir::Value pred1 = builder.create( - loc, mlir::arith::CmpIPredicate::eq, eleSize, stride); + mlir::Value pred1 = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, eleSize, stride); mlir::Value extent = dimInfo.getExtent(); - mlir::Value pred2 = builder.create( - loc, mlir::arith::CmpIPredicate::eq, extent, zero); + mlir::Value pred2 = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, extent, zero); mlir::Value result = - builder.create(loc, pred1, pred2); + mlir::arith::OrIOp::create(builder, loc, pred1, pred2); result = builder.createConvert(loc, op.getType(), result); rewriter.replaceOp(op, result); return mlir::success(); @@ -192,7 +192,7 @@ class DoConcurrentConversion // TODO Should this be a heap allocation instead? For now, we allocate // on the stack for each loop iteration. mlir::Value localAlloc = - rewriter.create(loop.getLoc(), localizer.getType()); + fir::AllocaOp::create(rewriter, loop.getLoc(), localizer.getType()); auto cloneLocalizerRegion = [&](mlir::Region ®ion, mlir::ValueRange regionArgs, @@ -258,10 +258,10 @@ class DoConcurrentConversion for (auto [lb, ub, st, iv] : llvm::zip_equal(loop.getLowerBound(), loop.getUpperBound(), loop.getStep(), *loop.getLoopInductionVars())) { - innermostUnorderdLoop = rewriter.create( - doConcurentOp.getLoc(), lb, ub, st, + innermostUnorderdLoop = fir::DoLoopOp::create( + rewriter, doConcurentOp.getLoc(), lb, ub, st, /*unordred=*/true, /*finalCountValue=*/false, - /*iterArgs=*/std::nullopt, loop.getReduceVars(), + /*iterArgs=*/mlir::ValueRange{}, loop.getReduceVars(), loop.getReduceAttrsAttr()); ivArgs.push_back(innermostUnorderdLoop.getInductionVar()); rewriter.setInsertionPointToStart(innermostUnorderdLoop.getBody()); diff --git a/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp b/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp index 4d25a02bf18ba..49a085ee3b336 100644 --- a/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp +++ b/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp @@ -284,7 +284,7 @@ genReductionLoop(fir::FirOpBuilder &builder, mlir::func::FuncOp &funcOp, fir::SequenceType::getUnknownExtent()); mlir::Type arrTy = fir::SequenceType::get(flatShape, elementType); mlir::Type boxArrTy = fir::BoxType::get(arrTy); - mlir::Value array = builder.create(loc, boxArrTy, arg); + mlir::Value array = fir::ConvertOp::create(builder, loc, boxArrTy, arg); mlir::Type resultType = funcOp.getResultTypes()[0]; mlir::Value init = initVal(builder, loc, resultType); @@ -299,11 +299,11 @@ genReductionLoop(fir::FirOpBuilder &builder, mlir::func::FuncOp &funcOp, // should be able to optimize the redundancy. for (unsigned i = 0; i < rank; ++i) { mlir::Value dimIdx = builder.createIntegerConstant(loc, idxTy, i); - auto dims = - builder.create(loc, idxTy, idxTy, idxTy, array, dimIdx); + auto dims = fir::BoxDimsOp::create(builder, loc, idxTy, idxTy, idxTy, array, + dimIdx); mlir::Value len = dims.getResult(1); // We use C indexing here, so len-1 as loopcount - mlir::Value loopCount = builder.create(loc, len, one); + mlir::Value loopCount = mlir::arith::SubIOp::create(builder, loc, len, one); bounds.push_back(loopCount); } // Create a loop nest consisting of OP operations. @@ -316,9 +316,9 @@ genReductionLoop(fir::FirOpBuilder &builder, mlir::func::FuncOp &funcOp, for (unsigned i = rank; 0 < i; --i) { mlir::Value step = one; mlir::Value loopCount = bounds[i - 1]; - auto loop = builder.create(loc, zeroIdx, loopCount, step, - unorderedOrInitialLoopCond, - /*finalCountValue=*/false, init); + auto loop = OP::create(builder, loc, zeroIdx, loopCount, step, + unorderedOrInitialLoopCond, + /*finalCountValue=*/false, init); init = loop.getRegionIterArgs()[resultIndex]; indices.push_back(loop.getInductionVar()); // Set insertion point to the loop body so that the next loop @@ -332,8 +332,8 @@ genReductionLoop(fir::FirOpBuilder &builder, mlir::func::FuncOp &funcOp, // We are in the innermost loop: generate the reduction body. mlir::Type eleRefTy = builder.getRefType(elementType); mlir::Value addr = - builder.create(loc, eleRefTy, array, indices); - mlir::Value elem = builder.create(loc, addr); + fir::CoordinateOp::create(builder, loc, eleRefTy, array, indices); + mlir::Value elem = fir::LoadOp::create(builder, loc, addr); mlir::Value reductionVal = genBody(builder, loc, elementType, elem, init); // Generate vector with condition to continue while loop at [0] and result // from current loop at [1] for IterWhileOp loops, just result at [0] for @@ -344,7 +344,7 @@ genReductionLoop(fir::FirOpBuilder &builder, mlir::func::FuncOp &funcOp, // to return the updated value of the reduction to the enclosing // loops. for (unsigned i = 0; i < rank; ++i) { - auto result = builder.create(loc, results); + auto result = fir::ResultOp::create(builder, loc, results); // Proceed to the outer loop. auto loop = mlir::cast(result->getParentOp()); results = loop.getResults(); @@ -354,7 +354,7 @@ genReductionLoop(fir::FirOpBuilder &builder, mlir::func::FuncOp &funcOp, } // End of loop nest. The insertion point is after the outermost loop. // Return the reduction value from the function. - builder.create(loc, results[resultIndex]); + mlir::func::ReturnOp::create(builder, loc, results[resultIndex]); } static llvm::SmallVector nopLoopCond(fir::FirOpBuilder &builder, @@ -394,9 +394,9 @@ static void genRuntimeSumBody(fir::FirOpBuilder &builder, mlir::Type elementType, mlir::Value elem1, mlir::Value elem2) -> mlir::Value { if (mlir::isa(elementType)) - return builder.create(loc, elem1, elem2); + return mlir::arith::AddFOp::create(builder, loc, elem1, elem2); if (mlir::isa(elementType)) - return builder.create(loc, elem1, elem2); + return mlir::arith::AddIOp::create(builder, loc, elem1, elem2); llvm_unreachable("unsupported type"); return {}; @@ -436,12 +436,12 @@ static void genRuntimeMaxvalBody(fir::FirOpBuilder &builder, // This libm function may not work properly for F128 arguments // on targets where long double is not F128. It is an LLVM issue, // but we just use normal select here to resolve all the cases. - auto compare = builder.create( - loc, mlir::arith::CmpFPredicate::OGT, elem1, elem2); - return builder.create(loc, compare, elem1, elem2); + auto compare = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::OGT, elem1, elem2); + return mlir::arith::SelectOp::create(builder, loc, compare, elem1, elem2); } if (mlir::isa(elementType)) - return builder.create(loc, elem1, elem2); + return mlir::arith::MaxSIOp::create(builder, loc, elem1, elem2); llvm_unreachable("unsupported type"); return {}; @@ -472,11 +472,11 @@ static void genRuntimeCountBody(fir::FirOpBuilder &builder, auto zero64 = builder.createIntegerConstant(loc, builder.getI64Type(), 0); auto one64 = builder.createIntegerConstant(loc, builder.getI64Type(), 1); - auto compare = builder.create( - loc, mlir::arith::CmpIPredicate::eq, elem1, zero32); + auto compare = mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::eq, elem1, zero32); auto select = - builder.create(loc, compare, zero64, one64); - return builder.create(loc, select, elem2); + mlir::arith::SelectOp::create(builder, loc, compare, zero64, one64); + return mlir::arith::AddIOp::create(builder, loc, select, elem2); }; // Count always gets I32 for elementType as it converts logical input to @@ -501,14 +501,14 @@ static void genRuntimeAnyBody(fir::FirOpBuilder &builder, mlir::Type elementType, mlir::Value elem1, mlir::Value elem2) -> mlir::Value { auto zero = builder.createIntegerConstant(loc, elementType, 0); - return builder.create( - loc, mlir::arith::CmpIPredicate::ne, elem1, zero); + return mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::ne, elem1, zero); }; auto continueCond = [](fir::FirOpBuilder builder, mlir::Location loc, mlir::Value reductionVal) { auto one1 = builder.createIntegerConstant(loc, builder.getI1Type(), 1); - auto eor = builder.create(loc, reductionVal, one1); + auto eor = mlir::arith::XOrIOp::create(builder, loc, reductionVal, one1); llvm::SmallVector results = {eor, reductionVal}; return results; }; @@ -534,8 +534,8 @@ static void genRuntimeAllBody(fir::FirOpBuilder &builder, mlir::Type elementType, mlir::Value elem1, mlir::Value elem2) -> mlir::Value { auto zero = builder.createIntegerConstant(loc, elementType, 0); - return builder.create( - loc, mlir::arith::CmpIPredicate::ne, elem1, zero); + return mlir::arith::CmpIOp::create( + builder, loc, mlir::arith::CmpIPredicate::ne, elem1, zero); }; auto continueCond = [](fir::FirOpBuilder builder, mlir::Location loc, @@ -577,13 +577,13 @@ void fir::genMinMaxlocReductionLoop( fir::SequenceType::getUnknownExtent()); mlir::Type arrTy = fir::SequenceType::get(flatShape, elementType); mlir::Type boxArrTy = fir::BoxType::get(arrTy); - array = builder.create(loc, boxArrTy, array); + array = fir::ConvertOp::create(builder, loc, boxArrTy, array); mlir::Type resultElemType = hlfir::getFortranElementType(resultArr.getType()); mlir::Value flagSet = builder.createIntegerConstant(loc, resultElemType, 1); mlir::Value zero = builder.createIntegerConstant(loc, resultElemType, 0); mlir::Value flagRef = builder.createTemporary(loc, resultElemType); - builder.create(loc, zero, flagRef); + fir::StoreOp::create(builder, loc, zero, flagRef); mlir::Value init = initVal(builder, loc, elementType); llvm::SmallVector bounds; @@ -597,11 +597,11 @@ void fir::genMinMaxlocReductionLoop( // should be able to optimize the redundancy. for (unsigned i = 0; i < rank; ++i) { mlir::Value dimIdx = builder.createIntegerConstant(loc, idxTy, i); - auto dims = - builder.create(loc, idxTy, idxTy, idxTy, array, dimIdx); + auto dims = fir::BoxDimsOp::create(builder, loc, idxTy, idxTy, idxTy, array, + dimIdx); mlir::Value len = dims.getResult(1); // We use C indexing here, so len-1 as loopcount - mlir::Value loopCount = builder.create(loc, len, one); + mlir::Value loopCount = mlir::arith::SubIOp::create(builder, loc, len, one); bounds.push_back(loopCount); } // Create a loop nest consisting of OP operations. @@ -615,8 +615,8 @@ void fir::genMinMaxlocReductionLoop( mlir::Value step = one; mlir::Value loopCount = bounds[i - 1]; auto loop = - builder.create(loc, zeroIdx, loopCount, step, false, - /*finalCountValue=*/false, init); + fir::DoLoopOp::create(builder, loc, zeroIdx, loopCount, step, false, + /*finalCountValue=*/false, init); init = loop.getRegionIterArgs()[0]; indices.push_back(loop.getInductionVar()); // Set insertion point to the loop body so that the next loop @@ -634,7 +634,7 @@ void fir::genMinMaxlocReductionLoop( // to return the updated value of the reduction to the enclosing // loops. for (unsigned i = 0; i < rank; ++i) { - auto result = builder.create(loc, reductionVal); + auto result = fir::ResultOp::create(builder, loc, reductionVal); // Proceed to the outer loop. auto loop = mlir::cast(result->getParentOp()); reductionVal = loop.getResult(0); @@ -646,7 +646,7 @@ void fir::genMinMaxlocReductionLoop( if (maskMayBeLogicalScalar) { if (fir::IfOp ifOp = mlir::dyn_cast(builder.getBlock()->getParentOp())) { - builder.create(loc, reductionVal); + fir::ResultOp::create(builder, loc, reductionVal); builder.setInsertionPointAfter(ifOp); // Redefine flagSet to escape scope of ifOp flagSet = builder.createIntegerConstant(loc, resultElemType, 1); @@ -689,10 +689,11 @@ static void genRuntimeMinMaxlocBody(fir::FirOpBuilder &builder, mlir::Value returnValue = builder.createIntegerConstant(loc, resultElemTy, 0); mlir::Value resultArrSize = builder.createIntegerConstant(loc, idxTy, rank); - mlir::Value resultArrInit = builder.create(loc, resultTy); - mlir::Value resultArrShape = builder.create(loc, resultArrSize); - mlir::Value resultArr = builder.create( - loc, resultBoxTy, resultArrInit, resultArrShape); + mlir::Value resultArrInit = fir::AllocMemOp::create(builder, loc, resultTy); + mlir::Value resultArrShape = + fir::ShapeOp::create(builder, loc, resultArrSize); + mlir::Value resultArr = fir::EmboxOp::create(builder, loc, resultBoxTy, + resultArrInit, resultArrShape); mlir::Type resultRefTy = builder.getRefType(resultElemTy); @@ -701,14 +702,14 @@ static void genRuntimeMinMaxlocBody(fir::FirOpBuilder &builder, fir::SequenceType::getUnknownExtent()); mlir::Type maskTy = fir::SequenceType::get(flatShape, maskElemType); mlir::Type boxMaskTy = fir::BoxType::get(maskTy); - mask = builder.create(loc, boxMaskTy, mask); + mask = fir::ConvertOp::create(builder, loc, boxMaskTy, mask); } for (unsigned int i = 0; i < rank; ++i) { mlir::Value index = builder.createIntegerConstant(loc, idxTy, i); mlir::Value resultElemAddr = - builder.create(loc, resultRefTy, resultArr, index); - builder.create(loc, returnValue, resultElemAddr); + fir::CoordinateOp::create(builder, loc, resultRefTy, resultArr, index); + fir::StoreOp::create(builder, loc, returnValue, resultElemAddr); } auto genBodyOp = @@ -720,29 +721,30 @@ static void genRuntimeMinMaxlocBody(fir::FirOpBuilder &builder, if (maskRank > 0) { mlir::Type logicalRef = builder.getRefType(maskElemType); mlir::Value maskAddr = - builder.create(loc, logicalRef, mask, indices); - mlir::Value maskElem = builder.create(loc, maskAddr); + fir::CoordinateOp::create(builder, loc, logicalRef, mask, indices); + mlir::Value maskElem = fir::LoadOp::create(builder, loc, maskAddr); // fir::IfOp requires argument to be I1 - won't accept logical or any // other Integer. mlir::Type ifCompatType = builder.getI1Type(); mlir::Value ifCompatElem = - builder.create(loc, ifCompatType, maskElem); + fir::ConvertOp::create(builder, loc, ifCompatType, maskElem); llvm::SmallVector resultsTy = {elementType, elementType}; - fir::IfOp ifOp = builder.create(loc, elementType, ifCompatElem, - /*withElseRegion=*/true); + fir::IfOp ifOp = + fir::IfOp::create(builder, loc, elementType, ifCompatElem, + /*withElseRegion=*/true); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); } // Set flag that mask was true at some point mlir::Value flagSet = builder.createIntegerConstant( loc, mlir::cast(flagRef.getType()).getEleTy(), 1); - mlir::Value isFirst = builder.create(loc, flagRef); + mlir::Value isFirst = fir::LoadOp::create(builder, loc, flagRef); mlir::Type eleRefTy = builder.getRefType(elementType); mlir::Value addr = - builder.create(loc, eleRefTy, array, indices); - mlir::Value elem = builder.create(loc, addr); + fir::CoordinateOp::create(builder, loc, eleRefTy, array, indices); + mlir::Value elem = fir::LoadOp::create(builder, loc, addr); mlir::Value cmp; if (mlir::isa(elementType)) { @@ -750,38 +752,37 @@ static void genRuntimeMinMaxlocBody(fir::FirOpBuilder &builder, // is not NaN. A OGL/OLT condition will usually work for this unless all // the values are Nan or Inf. This follows the same logic as // NumericCompare for Minloc/Maxlox in extrema.cpp. - cmp = builder.create( - loc, - isMax ? mlir::arith::CmpFPredicate::OGT - : mlir::arith::CmpFPredicate::OLT, - elem, reduction); - - mlir::Value cmpNan = builder.create( - loc, mlir::arith::CmpFPredicate::UNE, reduction, reduction); - mlir::Value cmpNan2 = builder.create( - loc, mlir::arith::CmpFPredicate::OEQ, elem, elem); - cmpNan = builder.create(loc, cmpNan, cmpNan2); - cmp = builder.create(loc, cmp, cmpNan); + cmp = mlir::arith::CmpFOp::create(builder, loc, + isMax ? mlir::arith::CmpFPredicate::OGT + : mlir::arith::CmpFPredicate::OLT, + elem, reduction); + + mlir::Value cmpNan = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::UNE, reduction, reduction); + mlir::Value cmpNan2 = mlir::arith::CmpFOp::create( + builder, loc, mlir::arith::CmpFPredicate::OEQ, elem, elem); + cmpNan = mlir::arith::AndIOp::create(builder, loc, cmpNan, cmpNan2); + cmp = mlir::arith::OrIOp::create(builder, loc, cmp, cmpNan); } else if (mlir::isa(elementType)) { - cmp = builder.create( - loc, - isMax ? mlir::arith::CmpIPredicate::sgt - : mlir::arith::CmpIPredicate::slt, - elem, reduction); + cmp = mlir::arith::CmpIOp::create(builder, loc, + isMax ? mlir::arith::CmpIPredicate::sgt + : mlir::arith::CmpIPredicate::slt, + elem, reduction); } else { llvm_unreachable("unsupported type"); } // The condition used for the loop is isFirst || . - isFirst = builder.create(loc, cmp.getType(), isFirst); - isFirst = builder.create( - loc, isFirst, builder.createIntegerConstant(loc, cmp.getType(), 1)); - cmp = builder.create(loc, cmp, isFirst); - fir::IfOp ifOp = builder.create(loc, elementType, cmp, - /*withElseRegion*/ true); + isFirst = fir::ConvertOp::create(builder, loc, cmp.getType(), isFirst); + isFirst = mlir::arith::XOrIOp::create( + builder, loc, isFirst, + builder.createIntegerConstant(loc, cmp.getType(), 1)); + cmp = mlir::arith::OrIOp::create(builder, loc, cmp, isFirst); + fir::IfOp ifOp = fir::IfOp::create(builder, loc, elementType, cmp, + /*withElseRegion*/ true); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); - builder.create(loc, flagSet, flagRef); + fir::StoreOp::create(builder, loc, flagSet, flagRef); mlir::Type resultElemTy = hlfir::getFortranElementType(resultArr.getType()); mlir::Type returnRefTy = builder.getRefType(resultElemTy); mlir::IndexType idxTy = builder.getIndexType(); @@ -790,17 +791,17 @@ static void genRuntimeMinMaxlocBody(fir::FirOpBuilder &builder, for (unsigned int i = 0; i < rank; ++i) { mlir::Value index = builder.createIntegerConstant(loc, idxTy, i); - mlir::Value resultElemAddr = - builder.create(loc, returnRefTy, resultArr, index); + mlir::Value resultElemAddr = fir::CoordinateOp::create( + builder, loc, returnRefTy, resultArr, index); mlir::Value convert = - builder.create(loc, resultElemTy, indices[i]); + fir::ConvertOp::create(builder, loc, resultElemTy, indices[i]); mlir::Value fortranIndex = - builder.create(loc, convert, one); - builder.create(loc, fortranIndex, resultElemAddr); + mlir::arith::AddIOp::create(builder, loc, convert, one); + fir::StoreOp::create(builder, loc, fortranIndex, resultElemAddr); } - builder.create(loc, elem); + fir::ResultOp::create(builder, loc, elem); builder.setInsertionPointToStart(&ifOp.getElseRegion().front()); - builder.create(loc, reduction); + fir::ResultOp::create(builder, loc, reduction); builder.setInsertionPointAfter(ifOp); mlir::Value reductionVal = ifOp.getResult(0); @@ -808,9 +809,9 @@ static void genRuntimeMinMaxlocBody(fir::FirOpBuilder &builder, if (maskRank > 0) { fir::IfOp ifOp = mlir::dyn_cast(builder.getBlock()->getParentOp()); - builder.create(loc, reductionVal); + fir::ResultOp::create(builder, loc, reductionVal); builder.setInsertionPointToStart(&ifOp.getElseRegion().front()); - builder.create(loc, reduction); + fir::ResultOp::create(builder, loc, reduction); reductionVal = ifOp.getResult(0); builder.setInsertionPointAfter(ifOp); } @@ -825,12 +826,12 @@ static void genRuntimeMinMaxlocBody(fir::FirOpBuilder &builder, mlir::Type logical = maskElemType; mlir::Type logicalRefTy = builder.getRefType(logical); mlir::Value condAddr = - builder.create(loc, logicalRefTy, mask); - mlir::Value cond = builder.create(loc, condAddr); - mlir::Value condI1 = builder.create(loc, i1Type, cond); + fir::BoxAddrOp::create(builder, loc, logicalRefTy, mask); + mlir::Value cond = fir::LoadOp::create(builder, loc, condAddr); + mlir::Value condI1 = fir::ConvertOp::create(builder, loc, i1Type, cond); - fir::IfOp ifOp = builder.create(loc, elementType, condI1, - /*withElseRegion=*/true); + fir::IfOp ifOp = fir::IfOp::create(builder, loc, elementType, condI1, + /*withElseRegion=*/true); builder.setInsertionPointToStart(&ifOp.getElseRegion().front()); mlir::Value basicValue; @@ -839,7 +840,7 @@ static void genRuntimeMinMaxlocBody(fir::FirOpBuilder &builder, } else { basicValue = builder.createRealConstant(loc, elementType, 0); } - builder.create(loc, basicValue); + fir::ResultOp::create(builder, loc, basicValue); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); } @@ -847,8 +848,8 @@ static void genRuntimeMinMaxlocBody(fir::FirOpBuilder &builder, const mlir::Type &resultElemType, mlir::Value resultArr, mlir::Value index) { mlir::Type resultRefTy = builder.getRefType(resultElemType); - return builder.create(loc, resultRefTy, resultArr, - index); + return fir::CoordinateOp::create(builder, loc, resultRefTy, resultArr, + index); }; genMinMaxlocReductionLoop(builder, funcOp.front().getArgument(1), init, @@ -859,25 +860,26 @@ static void genRuntimeMinMaxlocBody(fir::FirOpBuilder &builder, if (isDim) { mlir::Type resultBoxTy = fir::BoxType::get(fir::HeapType::get(resultElemTy)); - mlir::Value outputArr = builder.create( - loc, builder.getRefType(resultBoxTy), funcOp.front().getArgument(0)); - mlir::Value resultArrScalar = builder.create( - loc, fir::HeapType::get(resultElemTy), resultArrInit); + mlir::Value outputArr = + fir::ConvertOp::create(builder, loc, builder.getRefType(resultBoxTy), + funcOp.front().getArgument(0)); + mlir::Value resultArrScalar = fir::ConvertOp::create( + builder, loc, fir::HeapType::get(resultElemTy), resultArrInit); mlir::Value resultBox = - builder.create(loc, resultBoxTy, resultArrScalar); - builder.create(loc, resultBox, outputArr); + fir::EmboxOp::create(builder, loc, resultBoxTy, resultArrScalar); + fir::StoreOp::create(builder, loc, resultBox, outputArr); } else { fir::SequenceType::Shape resultShape(1, rank); mlir::Type outputArrTy = fir::SequenceType::get(resultShape, resultElemTy); mlir::Type outputHeapTy = fir::HeapType::get(outputArrTy); mlir::Type outputBoxTy = fir::BoxType::get(outputHeapTy); mlir::Type outputRefTy = builder.getRefType(outputBoxTy); - mlir::Value outputArr = builder.create( - loc, outputRefTy, funcOp.front().getArgument(0)); - builder.create(loc, resultArr, outputArr); + mlir::Value outputArr = fir::ConvertOp::create( + builder, loc, outputRefTy, funcOp.front().getArgument(0)); + fir::StoreOp::create(builder, loc, resultArr, outputArr); } - builder.create(loc); + mlir::func::ReturnOp::create(builder, loc); } /// Generate function type for the simplified version of RTNAME(DotProduct) @@ -929,10 +931,10 @@ static void genRuntimeDotBody(fir::FirOpBuilder &builder, fir::SequenceType::Shape flatShape = {fir::SequenceType::getUnknownExtent()}; mlir::Type arrTy1 = fir::SequenceType::get(flatShape, arg1ElementTy); mlir::Type boxArrTy1 = fir::BoxType::get(arrTy1); - mlir::Value array1 = builder.create(loc, boxArrTy1, arg1); + mlir::Value array1 = fir::ConvertOp::create(builder, loc, boxArrTy1, arg1); mlir::Type arrTy2 = fir::SequenceType::get(flatShape, arg2ElementTy); mlir::Type boxArrTy2 = fir::BoxType::get(arrTy2); - mlir::Value array2 = builder.create(loc, boxArrTy2, arg2); + mlir::Value array2 = fir::ConvertOp::create(builder, loc, boxArrTy2, arg2); // This version takes the loop trip count from the first argument. // If the first argument's box has unknown (at compilation time) // extent, then it may be better to take the extent from the second @@ -941,17 +943,17 @@ static void genRuntimeDotBody(fir::FirOpBuilder &builder, // function and some analysis at the call site to choose which version // is more profitable to call. // Note that we can assume that both arguments have the same extent. - auto dims = - builder.create(loc, idxTy, idxTy, idxTy, array1, zeroIdx); + auto dims = fir::BoxDimsOp::create(builder, loc, idxTy, idxTy, idxTy, array1, + zeroIdx); mlir::Value len = dims.getResult(1); mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1); mlir::Value step = one; // We use C indexing here, so len-1 as loopcount - mlir::Value loopCount = builder.create(loc, len, one); - auto loop = builder.create(loc, zeroIdx, loopCount, step, - /*unordered=*/false, - /*finalCountValue=*/false, zero); + mlir::Value loopCount = mlir::arith::SubIOp::create(builder, loc, len, one); + auto loop = fir::DoLoopOp::create(builder, loc, zeroIdx, loopCount, step, + /*unordered=*/false, + /*finalCountValue=*/false, zero); mlir::Value sumVal = loop.getRegionIterArgs()[0]; // Begin loop code @@ -961,33 +963,35 @@ static void genRuntimeDotBody(fir::FirOpBuilder &builder, mlir::Type eleRef1Ty = builder.getRefType(arg1ElementTy); mlir::Value index = loop.getInductionVar(); mlir::Value addr1 = - builder.create(loc, eleRef1Ty, array1, index); - mlir::Value elem1 = builder.create(loc, addr1); + fir::CoordinateOp::create(builder, loc, eleRef1Ty, array1, index); + mlir::Value elem1 = fir::LoadOp::create(builder, loc, addr1); // Convert to the result type. - elem1 = builder.create(loc, resultElementType, elem1); + elem1 = fir::ConvertOp::create(builder, loc, resultElementType, elem1); mlir::Type eleRef2Ty = builder.getRefType(arg2ElementTy); mlir::Value addr2 = - builder.create(loc, eleRef2Ty, array2, index); - mlir::Value elem2 = builder.create(loc, addr2); + fir::CoordinateOp::create(builder, loc, eleRef2Ty, array2, index); + mlir::Value elem2 = fir::LoadOp::create(builder, loc, addr2); // Convert to the result type. - elem2 = builder.create(loc, resultElementType, elem2); + elem2 = fir::ConvertOp::create(builder, loc, resultElementType, elem2); if (mlir::isa(resultElementType)) - sumVal = builder.create( - loc, builder.create(loc, elem1, elem2), sumVal); + sumVal = mlir::arith::AddFOp::create( + builder, loc, mlir::arith::MulFOp::create(builder, loc, elem1, elem2), + sumVal); else if (mlir::isa(resultElementType)) - sumVal = builder.create( - loc, builder.create(loc, elem1, elem2), sumVal); + sumVal = mlir::arith::AddIOp::create( + builder, loc, mlir::arith::MulIOp::create(builder, loc, elem1, elem2), + sumVal); else llvm_unreachable("unsupported type"); - builder.create(loc, sumVal); + fir::ResultOp::create(builder, loc, sumVal); // End of loop. builder.restoreInsertionPoint(loopEndPt); mlir::Value resultVal = loop.getResult(0); - builder.create(loc, resultVal); + mlir::func::ReturnOp::create(builder, loc, resultVal); } mlir::func::FuncOp SimplifyIntrinsicsPass::getOrCreateFunction( @@ -1229,8 +1233,8 @@ void SimplifyIntrinsicsPass::simplifyMinMaxlocReduction( mlir::func::FuncOp newFunc = getOrCreateFunction(builder, funcName, typeGenerator, bodyGenerator); - builder.create(loc, newFunc, - mlir::ValueRange{args[0], args[1], mask}); + fir::CallOp::create(builder, loc, newFunc, + mlir::ValueRange{args[0], args[1], mask}); call->dropAllReferences(); call->erase(); } @@ -1259,7 +1263,7 @@ void SimplifyIntrinsicsPass::simplifyReductionBody( mlir::func::FuncOp newFunc = getOrCreateFunction(builder, funcName, typeGenerator, bodyGenerator); auto newCall = - builder.create(loc, newFunc, mlir::ValueRange{args[0]}); + fir::CallOp::create(builder, loc, newFunc, mlir::ValueRange{args[0]}); call->replaceAllUsesWith(newCall.getResults()); call->dropAllReferences(); call->erase(); @@ -1344,8 +1348,8 @@ void SimplifyIntrinsicsPass::runOnOperation() { mlir::func::FuncOp newFunc = getOrCreateFunction( builder, typedFuncName, typeGenerator, bodyGenerator); - auto newCall = builder.create(loc, newFunc, - mlir::ValueRange{v1, v2}); + auto newCall = fir::CallOp::create(builder, loc, newFunc, + mlir::ValueRange{v1, v2}); call->replaceAllUsesWith(newCall.getResults()); call->dropAllReferences(); call->erase(); diff --git a/flang/lib/Optimizer/Transforms/StackArrays.cpp b/flang/lib/Optimizer/Transforms/StackArrays.cpp index bc8a9497fbb70..0d131291feef3 100644 --- a/flang/lib/Optimizer/Transforms/StackArrays.cpp +++ b/flang/lib/Optimizer/Transforms/StackArrays.cpp @@ -569,7 +569,7 @@ static mlir::Value convertAllocationType(mlir::PatternRewriter &rewriter, auto insertionPoint = rewriter.saveInsertionPoint(); rewriter.setInsertionPointAfter(stack.getDefiningOp()); mlir::Value conv = - rewriter.create(loc, firHeapTy, stack).getResult(); + fir::ConvertOp::create(rewriter, loc, firHeapTy, stack).getResult(); rewriter.restoreInsertionPoint(insertionPoint); return conv; } @@ -758,9 +758,9 @@ AllocMemConversion::insertAlloca(fir::AllocMemOp &oldAlloc, llvm::StringRef uniqName = unpackName(oldAlloc.getUniqName()); llvm::StringRef bindcName = unpackName(oldAlloc.getBindcName()); - auto alloca = rewriter.create(loc, varTy, uniqName, bindcName, - oldAlloc.getTypeparams(), - oldAlloc.getShape()); + auto alloca = + fir::AllocaOp::create(rewriter, loc, varTy, uniqName, bindcName, + oldAlloc.getTypeparams(), oldAlloc.getShape()); if (emitLifetimeMarkers) insertLifetimeMarkers(oldAlloc, alloca, rewriter); diff --git a/flang/lib/Parser/message.cpp b/flang/lib/Parser/message.cpp index 909fba948a45a..2a8101dd0b810 100644 --- a/flang/lib/Parser/message.cpp +++ b/flang/lib/Parser/message.cpp @@ -453,7 +453,7 @@ void Messages::ResolveProvenances(const AllCookedSources &allCooked) { void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked, bool echoSourceLines, const common::LanguageFeatureControl *hintFlagPtr, - std::size_t maxErrorsToEmit) const { + std::size_t maxErrorsToEmit, bool warningsAreErrors) const { std::vector sorted; for (const auto &msg : messages_) { sorted.push_back(&msg); @@ -469,7 +469,7 @@ void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked, } msg->Emit(o, allCooked, echoSourceLines, hintFlagPtr); lastMsg = msg; - if (msg->IsFatal()) { + if (warningsAreErrors || msg->IsFatal()) { ++errorsEmitted; } // If maxErrorsToEmit is 0, emit all errors, otherwise break after @@ -491,7 +491,18 @@ void Messages::AttachTo(Message &msg, std::optional severity) { messages_.clear(); } -bool Messages::AnyFatalError() const { +bool Messages::AnyFatalError(bool warningsAreErrors) const { + // Short-circuit in the most common case. + if (messages_.empty()) { + return false; + } + // If warnings are errors and there are warnings or errors, this is fatal. + // This preserves the compiler's current behavior of treating any non-fatal + // message as a warning. We may want to refine this in the future. + if (warningsAreErrors) { + return true; + } + // Otherwise, check the message buffer for fatal errors. for (const auto &msg : messages_) { if (msg.IsFatal()) { return true; diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 76c9499410017..d349d8ceb0bb5 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -274,6 +274,10 @@ TYPE_PARSER( // construct(Parser{}) || construct(Parser{})) +// 2.15.3.6 REDUCTION (reduction-identifier: variable-name-list) +TYPE_PARSER(construct(Parser{}) || + construct(Parser{})) + TYPE_PARSER(construct( // Parser{}, ":"_tok >> nonemptyList(Parser{}), @@ -442,9 +446,18 @@ TYPE_PARSER(construct( TYPE_PARSER(construct(scalarIntExpr)) +TYPE_PARSER(construct( // + "ALWAYS" >> pure(OmpAlwaysModifier::Value::Always))) + TYPE_PARSER(construct( // "SIMD" >> pure(OmpChunkModifier::Value::Simd))) +TYPE_PARSER(construct( // + "CLOSE" >> pure(OmpCloseModifier::Value::Close))) + +TYPE_PARSER(construct( // + "DELETE" >> pure(OmpDeleteModifier::Value::Delete))) + TYPE_PARSER(construct( "SINK" >> pure(OmpDependenceType::Value::Sink) || "SOURCE" >> pure(OmpDependenceType::Value::Source))) @@ -502,26 +515,16 @@ TYPE_PARSER(construct( // TYPE_PARSER(construct( // "MAPPER"_tok >> parenthesized(Parser{}))) -// map-type -> ALLOC | DELETE | FROM | RELEASE | TO | TOFROM +// map-type -> ALLOC | DELETE | FROM | RELEASE | STORAGE | TO | TOFROM TYPE_PARSER(construct( // "ALLOC" >> pure(OmpMapType::Value::Alloc) || - "DELETE" >> pure(OmpMapType::Value::Delete) || + // Parse "DELETE" as OmpDeleteModifier "FROM" >> pure(OmpMapType::Value::From) || "RELEASE" >> pure(OmpMapType::Value::Release) || + "STORAGE" >> pure(OmpMapType::Value::Storage) || "TO"_id >> pure(OmpMapType::Value::To) || "TOFROM" >> pure(OmpMapType::Value::Tofrom))) -// map-type-modifier -> ALWAYS | CLOSE | OMPX_HOLD | PRESENT -TYPE_PARSER(construct( - "ALWAYS" >> pure(OmpMapTypeModifier::Value::Always) || - "CLOSE" >> pure(OmpMapTypeModifier::Value::Close) || - "OMPX_HOLD" >> pure(OmpMapTypeModifier::Value::Ompx_Hold) || - "PRESENT" >> pure(OmpMapTypeModifier::Value::Present))) - -// 2.15.3.6 REDUCTION (reduction-identifier: variable-name-list) -TYPE_PARSER(construct(Parser{}) || - construct(Parser{})) - TYPE_PARSER(construct( "REPRODUCIBLE" >> pure(OmpOrderModifier::Value::Reproducible) || "UNCONSTRAINED" >> pure(OmpOrderModifier::Value::Unconstrained))) @@ -534,11 +537,22 @@ TYPE_PARSER(construct( TYPE_PARSER(construct( "STRICT" >> pure(OmpPrescriptiveness::Value::Strict))) +TYPE_PARSER(construct( // + "PRESENT" >> pure(OmpPresentModifier::Value::Present))) + TYPE_PARSER(construct( "INSCAN" >> pure(OmpReductionModifier::Value::Inscan) || "TASK" >> pure(OmpReductionModifier::Value::Task) || "DEFAULT" >> pure(OmpReductionModifier::Value::Default))) +TYPE_PARSER(construct( // + "REF_PTEE" >> pure(OmpRefModifier::Value::Ref_Ptee) || + "REF_PTR"_id >> pure(OmpRefModifier::Value::Ref_Ptr) || + "REF_PTR_PTEE" >> pure(OmpRefModifier::Value::Ref_Ptr_Ptee))) + +TYPE_PARSER(construct( // + "SELF" >> pure(OmpSelfModifier::Value::Self))) + TYPE_PARSER(construct( // "STEP" >> parenthesized(scalarIntExpr))) @@ -559,6 +573,9 @@ TYPE_PARSER(construct( "POINTER" >> pure(OmpVariableCategory::Value::Pointer) || "SCALAR" >> pure(OmpVariableCategory::Value::Scalar))) +TYPE_PARSER(construct( // + "OMPX_HOLD" >> pure(OmpxHoldModifier::Value::Ompx_Hold))) + // This could be auto-generated. TYPE_PARSER( sourced(construct(Parser{}))) @@ -611,10 +628,16 @@ TYPE_PARSER(sourced( construct(Parser{}))) TYPE_PARSER(sourced(construct( - sourced(construct(Parser{}) || + sourced(construct(Parser{}) || + construct(Parser{}) || + construct(Parser{}) || + construct(Parser{}) || + construct(Parser{}) || + construct(Parser{}) || construct(Parser{}) || construct(Parser{}) || - construct(Parser{}))))) + construct(Parser{}) || + construct(Parser{}))))) TYPE_PARSER( sourced(construct(Parser{}))) diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index fbe89c668fc13..8ed16905b5099 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -3007,8 +3007,15 @@ class UnparseVisitor { WALK_NESTED_ENUM(OmpPrescriptiveness, Value) // OMP prescriptiveness WALK_NESTED_ENUM(OmpMapType, Value) // OMP map-type WALK_NESTED_ENUM(OmpMapTypeModifier, Value) // OMP map-type-modifier + WALK_NESTED_ENUM(OmpAlwaysModifier, Value) + WALK_NESTED_ENUM(OmpCloseModifier, Value) + WALK_NESTED_ENUM(OmpDeleteModifier, Value) + WALK_NESTED_ENUM(OmpPresentModifier, Value) + WALK_NESTED_ENUM(OmpRefModifier, Value) + WALK_NESTED_ENUM(OmpSelfModifier, Value) WALK_NESTED_ENUM(OmpTraitSelectorName, Value) WALK_NESTED_ENUM(OmpTraitSetSelectorName, Value) + WALK_NESTED_ENUM(OmpxHoldModifier, Value) #undef WALK_NESTED_ENUM void Unparse(const ReductionOperator::Operator x) { diff --git a/flang/lib/Semantics/canonicalize-omp.cpp b/flang/lib/Semantics/canonicalize-omp.cpp index cf05d8463277f..77e2fd6ca5097 100644 --- a/flang/lib/Semantics/canonicalize-omp.cpp +++ b/flang/lib/Semantics/canonicalize-omp.cpp @@ -27,7 +27,8 @@ class CanonicalizationOfOmp { public: template bool Pre(T &) { return true; } template void Post(T &) {} - CanonicalizationOfOmp(parser::Messages &messages) : messages_{messages} {} + CanonicalizationOfOmp(SemanticsContext &context) + : context_{context}, messages_{context.messages()} {} void Post(parser::Block &block) { for (auto it{block.begin()}; it != block.end(); ++it) { @@ -88,6 +89,8 @@ class CanonicalizationOfOmp { CanonicalizeUtilityConstructs(spec); } + void Post(parser::OmpMapClause &map) { CanonicalizeMapModifiers(map); } + private: template T *GetConstructIf(parser::ExecutionPartConstruct &x) { if (auto *y{std::get_if(&x.u)}) { @@ -390,16 +393,58 @@ class CanonicalizationOfOmp { omps.erase(rlast.base(), omps.end()); } + // Map clause modifiers are parsed as per OpenMP 6.0 spec. That spec has + // changed properties of some of the modifiers, for example it has expanded + // map-type-modifier into 3 individual modifiers (one for each of the + // possible values of the original modifier), and the "map-type" modifier + // is no longer ultimate. + // To utilize the modifier validation framework for semantic checks, + // if the specified OpenMP version is less than 6.0, rewrite the affected + // modifiers back into the pre-6.0 forms. + void CanonicalizeMapModifiers(parser::OmpMapClause &map) { + unsigned version{context_.langOptions().OpenMPVersion}; + if (version >= 60) { + return; + } + + // Omp{Always, Close, Present, xHold}Modifier -> OmpMapTypeModifier + // OmpDeleteModifier -> OmpMapType + using Modifier = parser::OmpMapClause::Modifier; + using Modifiers = std::optional>; + auto &modifiers{std::get(map.t)}; + if (!modifiers) { + return; + } + + using MapTypeModifier = parser::OmpMapTypeModifier; + using MapType = parser::OmpMapType; + + for (auto &mod : *modifiers) { + if (std::holds_alternative(mod.u)) { + mod.u = MapTypeModifier(MapTypeModifier::Value::Always); + } else if (std::holds_alternative(mod.u)) { + mod.u = MapTypeModifier(MapTypeModifier::Value::Close); + } else if (std::holds_alternative(mod.u)) { + mod.u = MapTypeModifier(MapTypeModifier::Value::Present); + } else if (std::holds_alternative(mod.u)) { + mod.u = MapTypeModifier(MapTypeModifier::Value::Ompx_Hold); + } else if (std::holds_alternative(mod.u)) { + mod.u = MapType(MapType::Value::Delete); + } + } + } + // Mapping from the specification parts to the blocks that follow in the // same construct. This is for converting utility constructs to executable // constructs. std::map blockForSpec_; + SemanticsContext &context_; parser::Messages &messages_; }; -bool CanonicalizeOmp(parser::Messages &messages, parser::Program &program) { - CanonicalizationOfOmp omp{messages}; +bool CanonicalizeOmp(SemanticsContext &context, parser::Program &program) { + CanonicalizationOfOmp omp{context}; Walk(program, omp); - return !messages.AnyFatalError(); + return !context.messages().AnyFatalError(); } } // namespace Fortran::semantics diff --git a/flang/lib/Semantics/canonicalize-omp.h b/flang/lib/Semantics/canonicalize-omp.h index c45d6bbbf9062..3251218da35ed 100644 --- a/flang/lib/Semantics/canonicalize-omp.h +++ b/flang/lib/Semantics/canonicalize-omp.h @@ -11,11 +11,12 @@ namespace Fortran::parser { struct Program; -class Messages; -} // namespace Fortran::parser +} namespace Fortran::semantics { -bool CanonicalizeOmp(parser::Messages &messages, parser::Program &program); -} +class SemanticsContext; + +bool CanonicalizeOmp(SemanticsContext &context, parser::Program &program); +} // namespace Fortran::semantics #endif // FORTRAN_SEMANTICS_CANONICALIZE_OMP_H_ diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index f9d64485f1407..a2f2906af10b8 100644 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -151,8 +151,8 @@ class CheckHelper { void CheckProcedureAssemblyName(const Symbol &symbol); void CheckExplicitSave(const Symbol &); parser::Messages WhyNotInteroperableDerivedType(const Symbol &); - parser::Messages WhyNotInteroperableObject( - const Symbol &, bool allowNonInteroperableType = false); + parser::Messages WhyNotInteroperableObject(const Symbol &, + bool allowNonInteroperableType = false, bool forCommonBlock = false); parser::Messages WhyNotInteroperableFunctionResult(const Symbol &); parser::Messages WhyNotInteroperableProcedure(const Symbol &, bool isError); void CheckBindC(const Symbol &); @@ -519,11 +519,35 @@ void CheckHelper::Check(const Symbol &symbol) { } void CheckHelper::CheckCommonBlock(const Symbol &symbol) { + auto restorer{messages_.SetLocation(symbol.name())}; CheckGlobalName(symbol); if (symbol.attrs().test(Attr::BIND_C)) { CheckBindC(symbol); + for (auto ref : symbol.get().objects()) { + if (ref->has()) { + if (auto msgs{WhyNotInteroperableObject(*ref, + /*allowInteroperableType=*/false, /*forCommonBlock=*/true)}; + !msgs.empty()) { + parser::Message &reason{msgs.messages().front()}; + parser::Message *msg{nullptr}; + if (reason.IsFatal()) { + msg = messages_.Say(symbol.name(), + "'%s' may not be a member of BIND(C) COMMON block /%s/"_err_en_US, + ref->name(), symbol.name()); + } else { + msg = messages_.Say(symbol.name(), + "'%s' should not be a member of BIND(C) COMMON block /%s/"_warn_en_US, + ref->name(), symbol.name()); + } + if (msg) { + msg->Attach( + std::move(reason.set_severity(parser::Severity::Because))); + } + } + } + } } - for (MutableSymbolRef ref : symbol.get().objects()) { + for (auto ref : symbol.get().objects()) { if (ref->test(Symbol::Flag::CrayPointee)) { messages_.Say(ref->name(), "Cray pointee '%s' may not be a member of a COMMON block"_err_en_US, @@ -3154,14 +3178,16 @@ parser::Messages CheckHelper::WhyNotInteroperableDerivedType( } parser::Messages CheckHelper::WhyNotInteroperableObject( - const Symbol &symbol, bool allowNonInteroperableType) { + const Symbol &symbol, bool allowNonInteroperableType, bool forCommonBlock) { parser::Messages msgs; - if (examinedByWhyNotInteroperable_.find(symbol) != - examinedByWhyNotInteroperable_.end()) { - return msgs; + if (!forCommonBlock) { + if (examinedByWhyNotInteroperable_.find(symbol) != + examinedByWhyNotInteroperable_.end()) { + return msgs; + } + examinedByWhyNotInteroperable_.insert(symbol); } bool isExplicitBindC{symbol.attrs().test(Attr::BIND_C)}; - examinedByWhyNotInteroperable_.insert(symbol); CHECK(symbol.has()); if (isExplicitBindC && !symbol.owner().IsModule()) { msgs.Say(symbol.name(), @@ -3258,7 +3284,7 @@ parser::Messages CheckHelper::WhyNotInteroperableObject( msgs.Say(symbol.name(), "An interoperable pointer must not be CONTIGUOUS"_err_en_US); } - if (msgs.AnyFatalError()) { + if (!forCommonBlock && msgs.AnyFatalError()) { examinedByWhyNotInteroperable_.erase(symbol); } return msgs; @@ -3338,8 +3364,8 @@ parser::Messages CheckHelper::WhyNotInteroperableProcedure( // 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); + dummyMsgs = WhyNotInteroperableObject( + *dummy, allowNonInteroperableType, /*forCommonBlock=*/false); } else { CheckBindC(*dummy); } diff --git a/flang/lib/Semantics/check-do-forall.cpp b/flang/lib/Semantics/check-do-forall.cpp index cc1d4bf58745a..e258df86a4b1c 100644 --- a/flang/lib/Semantics/check-do-forall.cpp +++ b/flang/lib/Semantics/check-do-forall.cpp @@ -1180,7 +1180,9 @@ void DoForallChecker::Leave(const parser::IoControlSpec &ioControlSpec) { void DoForallChecker::Leave(const parser::OutputImpliedDo &outputImpliedDo) { const auto &control{std::get(outputImpliedDo.t)}; const parser::Name &name{control.name.thing.thing}; - context_.CheckIndexVarRedefine(name.source, *name.symbol); + if (name.symbol) { + context_.CheckIndexVarRedefine(name.source, *name.symbol); + } } void DoForallChecker::Leave(const parser::StatVariable &statVariable) { diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 2425265e196c6..8264e1d5e8fd9 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -37,6 +37,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Frontend/OpenMP/OMP.h" @@ -1156,8 +1157,7 @@ void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar( (sym->has() || sym->has())) { context_.Say(name->source, - "The module name or main program name cannot be in a " - "%s " + "The module name cannot be in a %s " "directive"_err_en_US, ContextDirectiveAsFortran()); } else if (!IsSaved(*name->symbol) && @@ -3399,23 +3399,22 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Detach &x) { } } -void OmpStructureChecker::CheckAllowedMapTypes( - const parser::OmpMapType::Value &type, - const std::list &allowedMapTypeList) { - if (!llvm::is_contained(allowedMapTypeList, type)) { - std::string commaSeparatedMapTypes; - llvm::interleave( - allowedMapTypeList.begin(), allowedMapTypeList.end(), - [&](const parser::OmpMapType::Value &mapType) { - commaSeparatedMapTypes.append(parser::ToUpperCaseLetters( - parser::OmpMapType::EnumToString(mapType))); - }, - [&] { commaSeparatedMapTypes.append(", "); }); - context_.Say(GetContext().clauseSource, - "Only the %s map types are permitted " - "for MAP clauses on the %s directive"_err_en_US, - commaSeparatedMapTypes, ContextDirectiveAsFortran()); +void OmpStructureChecker::CheckAllowedMapTypes(parser::OmpMapType::Value type, + llvm::ArrayRef allowed) { + if (llvm::is_contained(allowed, type)) { + return; } + + llvm::SmallVector names; + llvm::transform( + allowed, std::back_inserter(names), [](parser::OmpMapType::Value val) { + return parser::ToUpperCaseLetters( + parser::OmpMapType::EnumToString(val)); + }); + llvm::sort(names); + context_.Say(GetContext().clauseSource, + "Only the %s map types are permitted for MAP clauses on the %s directive"_err_en_US, + llvm::join(names, ", "), ContextDirectiveAsFortran()); } void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) { @@ -3436,27 +3435,62 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) { CheckIteratorModifier(*iter); } if (auto *type{OmpGetUniqueModifier(modifiers)}) { + using Directive = llvm::omp::Directive; using Value = parser::OmpMapType::Value; - switch (GetContext().directive) { - case llvm::omp::Directive::OMPD_target: - case llvm::omp::Directive::OMPD_target_teams: - case llvm::omp::Directive::OMPD_target_teams_distribute: - case llvm::omp::Directive::OMPD_target_teams_distribute_simd: - case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do: - case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd: - case llvm::omp::Directive::OMPD_target_data: - CheckAllowedMapTypes( - type->v, {Value::To, Value::From, Value::Tofrom, Value::Alloc}); - break; - case llvm::omp::Directive::OMPD_target_enter_data: - CheckAllowedMapTypes(type->v, {Value::To, Value::Alloc}); - break; - case llvm::omp::Directive::OMPD_target_exit_data: - CheckAllowedMapTypes( - type->v, {Value::From, Value::Release, Value::Delete}); - break; - default: - break; + + static auto isValidForVersion{ + [](parser::OmpMapType::Value t, unsigned version) { + switch (t) { + case parser::OmpMapType::Value::Alloc: + case parser::OmpMapType::Value::Delete: + case parser::OmpMapType::Value::Release: + return version < 60; + case parser::OmpMapType::Value::Storage: + return version >= 60; + default: + return true; + } + }}; + + llvm::SmallVector mapEnteringTypes{[&]() { + llvm::SmallVector result; + for (size_t i{0}; i != parser::OmpMapType::Value_enumSize; ++i) { + auto t{static_cast(i)}; + if (isValidForVersion(t, version) && IsMapEnteringType(t)) { + result.push_back(t); + } + } + return result; + }()}; + llvm::SmallVector mapExitingTypes{[&]() { + llvm::SmallVector result; + for (size_t i{0}; i != parser::OmpMapType::Value_enumSize; ++i) { + auto t{static_cast(i)}; + if (isValidForVersion(t, version) && IsMapExitingType(t)) { + result.push_back(t); + } + } + return result; + }()}; + + llvm::omp::Directive dir{GetContext().directive}; + llvm::ArrayRef leafs{ + llvm::omp::getLeafConstructsOrSelf(dir)}; + + if (llvm::is_contained(leafs, Directive::OMPD_target) || + llvm::is_contained(leafs, Directive::OMPD_target_data)) { + if (version >= 60) { + // Map types listed in the decay table. [6.0:276] + CheckAllowedMapTypes( + type->v, {Value::Storage, Value::From, Value::To, Value::Tofrom}); + } else { + CheckAllowedMapTypes( + type->v, {Value::Alloc, Value::From, Value::To, Value::Tofrom}); + } + } else if (llvm::is_contained(leafs, Directive::OMPD_target_enter_data)) { + CheckAllowedMapTypes(type->v, mapEnteringTypes); + } else if (llvm::is_contained(leafs, Directive::OMPD_target_exit_data)) { + CheckAllowedMapTypes(type->v, mapExitingTypes); } } diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index 6a877a5d0a7c0..f4a291dc255c8 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -179,8 +179,8 @@ class OmpStructureChecker void HasInvalidDistributeNesting(const parser::OpenMPLoopConstruct &x); void HasInvalidLoopBinding(const parser::OpenMPLoopConstruct &x); // specific clause related - void CheckAllowedMapTypes(const parser::OmpMapType::Value &, - const std::list &); + void CheckAllowedMapTypes( + parser::OmpMapType::Value, llvm::ArrayRef); const std::list &GetTraitPropertyList( const parser::OmpTraitSelector &); diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp index 53ec3827893d0..14473724f0f40 100644 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -178,7 +178,7 @@ class ArgumentAnalyzer { } // Find and return a user-defined assignment std::optional TryDefinedAssignment(); - std::optional GetDefinedAssignmentProc(); + std::optional GetDefinedAssignmentProc(bool &isAmbiguous); std::optional GetType(std::size_t) const; void Dump(llvm::raw_ostream &); @@ -191,7 +191,7 @@ class ArgumentAnalyzer { MaybeExpr AnalyzeExprOrWholeAssumedSizeArray(const parser::Expr &); bool AreConformable() const; const Symbol *FindBoundOp(parser::CharBlock, int passIndex, - const Symbol *&generic, bool isSubroutine); + const Symbol *&generic, bool isSubroutine, bool *isAmbiguous = nullptr); void AddAssignmentConversion( const DynamicType &lhsType, const DynamicType &rhsType); bool OkLogicalIntegerAssignment(TypeCategory lhs, TypeCategory rhs); @@ -199,7 +199,8 @@ class ArgumentAnalyzer { bool IsBOZLiteral(std::size_t i) const { return evaluate::IsBOZLiteral(GetExpr(i)); } - void SayNoMatch(const std::string &, bool isAssignment = false); + void SayNoMatch( + const std::string &, bool isAssignment = false, bool isAmbiguous = false); std::string TypeAsFortran(std::size_t); bool AnyUntypedOrMissingOperand(); @@ -4781,7 +4782,9 @@ std::optional ArgumentAnalyzer::TryDefinedAssignment() { return std::nullopt; // user-defined assignment not allowed for these args } auto restorer{context_.GetContextualMessages().SetLocation(source_)}; - if (std::optional procRef{GetDefinedAssignmentProc()}) { + bool isAmbiguous{false}; + if (std::optional procRef{ + GetDefinedAssignmentProc(isAmbiguous)}) { if (context_.inWhereBody() && !procRef->proc().IsElemental()) { // C1032 context_.Say( "Defined assignment in WHERE must be elemental, but '%s' is not"_err_en_US, @@ -4791,9 +4794,11 @@ std::optional ArgumentAnalyzer::TryDefinedAssignment() { return std::move(*procRef); } if (isDefined == Tristate::Yes) { - if (!lhsType || !rhsType || (lhsRank != rhsRank && rhsRank != 0) || + if (isAmbiguous || !lhsType || !rhsType || + (lhsRank != rhsRank && rhsRank != 0) || !OkLogicalIntegerAssignment(lhsType->category(), rhsType->category())) { - SayNoMatch("ASSIGNMENT(=)", true); + SayNoMatch( + "ASSIGNMENT(=)", /*isAssignment=*/true, /*isAmbiguous=*/isAmbiguous); } } else if (!fatalErrors_) { CheckAssignmentConformance(); @@ -4822,13 +4827,15 @@ bool ArgumentAnalyzer::OkLogicalIntegerAssignment( return true; } -std::optional ArgumentAnalyzer::GetDefinedAssignmentProc() { +std::optional ArgumentAnalyzer::GetDefinedAssignmentProc( + bool &isAmbiguous) { const Symbol *proc{nullptr}; bool isProcElemental{false}; std::optional passedObjectIndex; std::string oprNameString{"assignment(=)"}; parser::CharBlock oprName{oprNameString}; const auto &scope{context_.context().FindScope(source_)}; + isAmbiguous = false; { auto restorer{context_.GetContextualMessages().DiscardMessages()}; if (const Symbol *symbol{scope.FindSymbol(oprName)}) { @@ -4842,8 +4849,8 @@ std::optional ArgumentAnalyzer::GetDefinedAssignmentProc() { for (std::size_t i{0}; (!proc || isProcElemental) && i < actuals_.size(); ++i) { const Symbol *generic{nullptr}; - if (const Symbol * - binding{FindBoundOp(oprName, i, generic, /*isSubroutine=*/true)}) { + if (const Symbol *binding{FindBoundOp(oprName, i, generic, + /*isSubroutine=*/true, /*isAmbiguous=*/&isAmbiguous)}) { // ignore inaccessible type-bound ASSIGNMENT(=) generic if (!CheckAccessibleSymbol(scope, DEREF(generic))) { const Symbol *resolution{GetBindingResolution(GetType(i), *binding)}; @@ -4967,7 +4974,8 @@ bool ArgumentAnalyzer::AreConformable() const { // Look for a type-bound operator in the type of arg number passIndex. const Symbol *ArgumentAnalyzer::FindBoundOp(parser::CharBlock oprName, - int passIndex, const Symbol *&generic, bool isSubroutine) { + int passIndex, const Symbol *&generic, bool isSubroutine, + bool *isAmbiguous) { const auto *type{GetDerivedTypeSpec(GetType(passIndex))}; const semantics::Scope *scope{type ? type->scope() : nullptr}; if (scope) { @@ -4989,6 +4997,9 @@ const Symbol *ArgumentAnalyzer::FindBoundOp(parser::CharBlock oprName, // Use the most recent override of the binding, if any return scope->FindComponent(binding->name()); } else { + if (isAmbiguous) { + *isAmbiguous = pair.second; + } context_.EmitGenericResolutionError(*generic, pair.second, isSubroutine); } } @@ -5072,40 +5083,37 @@ void ArgumentAnalyzer::ConvertBOZAssignmentRHS(const DynamicType &lhsType) { } // Report error resolving opr when there is a user-defined one available -void ArgumentAnalyzer::SayNoMatch(const std::string &opr, bool isAssignment) { +void ArgumentAnalyzer::SayNoMatch( + const std::string &opr, bool isAssignment, bool isAmbiguous) { std::string type0{TypeAsFortran(0)}; auto rank0{actuals_[0]->Rank()}; + std::string prefix{"No intrinsic or user-defined "s + opr + " matches"}; + if (isAmbiguous) { + prefix = "Multiple specific procedures for the generic "s + opr + " match"; + } if (actuals_.size() == 1) { if (rank0 > 0) { - context_.Say("No intrinsic or user-defined %s matches " - "rank %d array of %s"_err_en_US, - opr, rank0, type0); + context_.Say("%s rank %d array of %s"_err_en_US, prefix, rank0, type0); } else { - context_.Say("No intrinsic or user-defined %s matches " - "operand type %s"_err_en_US, - opr, type0); + context_.Say("%s operand type %s"_err_en_US, prefix, type0); } } else { std::string type1{TypeAsFortran(1)}; auto rank1{actuals_[1]->Rank()}; if (rank0 > 0 && rank1 > 0 && rank0 != rank1) { - context_.Say("No intrinsic or user-defined %s matches " - "rank %d array of %s and rank %d array of %s"_err_en_US, - opr, rank0, type0, rank1, type1); + context_.Say("%s rank %d array of %s and rank %d array of %s"_err_en_US, + prefix, rank0, type0, rank1, type1); } else if (isAssignment && rank0 != rank1) { if (rank0 == 0) { - context_.Say("No intrinsic or user-defined %s matches " - "scalar %s and rank %d array of %s"_err_en_US, - opr, type0, rank1, type1); + context_.Say("%s scalar %s and rank %d array of %s"_err_en_US, prefix, + type0, rank1, type1); } else { - context_.Say("No intrinsic or user-defined %s matches " - "rank %d array of %s and scalar %s"_err_en_US, - opr, rank0, type0, type1); + context_.Say("%s rank %d array of %s and scalar %s"_err_en_US, prefix, + rank0, type0, type1); } } else { - context_.Say("No intrinsic or user-defined %s matches " - "operand types %s and %s"_err_en_US, - opr, type0, type1); + context_.Say( + "%s operand types %s and %s"_err_en_US, prefix, type0, type1); } } } diff --git a/flang/lib/Semantics/openmp-modifiers.cpp b/flang/lib/Semantics/openmp-modifiers.cpp index c84e832ee52a1..336ce4beb24ba 100644 --- a/flang/lib/Semantics/openmp-modifiers.cpp +++ b/flang/lib/Semantics/openmp-modifiers.cpp @@ -140,6 +140,22 @@ OmpGetDescriptor() { return desc; } +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"always-modifier", + /*props=*/ + { + {45, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {45, {Clause::OMPC_map}}, + }, + }; + return desc; +} + template <> const OmpModifierDescriptor &OmpGetDescriptor() { static const OmpModifierDescriptor desc{ @@ -156,6 +172,22 @@ const OmpModifierDescriptor &OmpGetDescriptor() { return desc; } +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"close-modifier", + /*props=*/ + { + {50, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {50, {Clause::OMPC_map}}, + }, + }; + return desc; +} + template <> const OmpModifierDescriptor &OmpGetDescriptor() { static const OmpModifierDescriptor desc{ @@ -173,6 +205,23 @@ const OmpModifierDescriptor &OmpGetDescriptor() { return desc; } +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"delete-modifier", + /*props=*/ + { + {45, {OmpProperty::Unique, OmpProperty::Ultimate}}, + {60, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {45, {Clause::OMPC_map}}, + }, + }; + return desc; +} + template <> const OmpModifierDescriptor &OmpGetDescriptor() { static const OmpModifierDescriptor desc{ @@ -347,6 +396,7 @@ const OmpModifierDescriptor &OmpGetDescriptor() { /*props=*/ { {45, {OmpProperty::Ultimate}}, + {60, {OmpProperty::Unique}}, }, /*clauses=*/ { @@ -367,6 +417,7 @@ const OmpModifierDescriptor &OmpGetDescriptor() { /*clauses=*/ { {45, {Clause::OMPC_map}}, + {60, {}}, }, }; return desc; @@ -420,6 +471,22 @@ const OmpModifierDescriptor &OmpGetDescriptor() { return desc; } +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"present-modifier", + /*props=*/ + { + {51, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {51, {Clause::OMPC_map}}, + }, + }; + return desc; +} + template <> const OmpModifierDescriptor & OmpGetDescriptor() { @@ -456,6 +523,38 @@ const OmpModifierDescriptor &OmpGetDescriptor() { return desc; } +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"ref-modifier", + /*props=*/ + { + {60, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {60, {Clause::OMPC_map}}, + }, + }; + return desc; +} + +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"self-modifier", + /*props=*/ + { + {60, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {60, {Clause::OMPC_map}}, + }, + }; + return desc; +} + template <> const OmpModifierDescriptor & OmpGetDescriptor() { @@ -522,4 +621,20 @@ const OmpModifierDescriptor &OmpGetDescriptor() { }; return desc; } + +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"ompx-hold-modifier", + /*props=*/ + { + {45, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {45, {Clause::OMPC_map}}, + }, + }; + return desc; +} } // namespace Fortran::semantics diff --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp index f43d2cc75620e..da14507aa9fe6 100644 --- a/flang/lib/Semantics/openmp-utils.cpp +++ b/flang/lib/Semantics/openmp-utils.cpp @@ -143,6 +143,31 @@ bool IsVarOrFunctionRef(const MaybeExpr &expr) { } } +bool IsMapEnteringType(parser::OmpMapType::Value type) { + switch (type) { + case parser::OmpMapType::Value::Alloc: + case parser::OmpMapType::Value::Storage: + case parser::OmpMapType::Value::To: + case parser::OmpMapType::Value::Tofrom: + return true; + default: + return false; + } +} + +bool IsMapExitingType(parser::OmpMapType::Value type) { + switch (type) { + case parser::OmpMapType::Value::Delete: + case parser::OmpMapType::Value::From: + case parser::OmpMapType::Value::Release: + case parser::OmpMapType::Value::Storage: + case parser::OmpMapType::Value::Tofrom: + return true; + default: + return false; + } +} + std::optional GetEvaluateExpr(const parser::Expr &parserExpr) { const parser::TypedExpr &typedExpr{parserExpr.typedExpr}; // ForwardOwningPointer typedExpr diff --git a/flang/lib/Semantics/openmp-utils.h b/flang/lib/Semantics/openmp-utils.h index a96c008fb26e7..001fbeb45ceec 100644 --- a/flang/lib/Semantics/openmp-utils.h +++ b/flang/lib/Semantics/openmp-utils.h @@ -59,6 +59,9 @@ bool IsExtendedListItem(const Symbol &sym); bool IsVariableListItem(const Symbol &sym); bool IsVarOrFunctionRef(const MaybeExpr &expr); +bool IsMapEnteringType(parser::OmpMapType::Value type); +bool IsMapExitingType(parser::OmpMapType::Value type); + std::optional GetEvaluateExpr(const parser::Expr &parserExpr); std::optional GetDynamicType( const parser::Expr &parserExpr); diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 151f4ccae634e..4c3e509b5a36d 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -138,6 +138,9 @@ class AccAttributeVisitor : DirectiveAttributeVisitor { void Post(const parser::OpenACCBlockConstruct &) { PopContext(); } bool Pre(const parser::OpenACCCombinedConstruct &); void Post(const parser::OpenACCCombinedConstruct &) { PopContext(); } + void Post(const parser::AccBeginCombinedDirective &) { + GetContext().withinConstruct = true; + } bool Pre(const parser::OpenACCDeclarativeConstruct &); void Post(const parser::OpenACCDeclarativeConstruct &) { PopContext(); } @@ -160,6 +163,18 @@ class AccAttributeVisitor : DirectiveAttributeVisitor { GetContext().withinConstruct = true; } + // TODO: We should probably also privatize ConcurrentBounds. + template + bool Pre(const parser::LoopBounds &x) { + if (!dirContext_.empty() && GetContext().withinConstruct) { + if (auto *symbol{ResolveAcc( + x.name.thing, Symbol::Flag::AccPrivate, currScope())}) { + AddToContextObjectWithDSA(*symbol, Symbol::Flag::AccPrivate); + } + } + return true; + } + bool Pre(const parser::OpenACCStandaloneConstruct &); void Post(const parser::OpenACCStandaloneConstruct &) { PopContext(); } void Post(const parser::AccStandaloneDirective &) { @@ -712,7 +727,9 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor { void Post(const parser::EorLabel &eorLabel) { CheckSourceLabel(eorLabel.v); } void Post(const parser::OmpMapClause &x) { - Symbol::Flag ompFlag = Symbol::Flag::OmpMapToFrom; + unsigned version{context_.langOptions().OpenMPVersion}; + std::optional ompFlag; + auto &mods{OmpGetModifiers(x)}; if (auto *mapType{OmpGetUniqueModifier(mods)}) { switch (mapType->v) { @@ -726,16 +743,33 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor { ompFlag = Symbol::Flag::OmpMapToFrom; break; case parser::OmpMapType::Value::Alloc: - ompFlag = Symbol::Flag::OmpMapAlloc; - break; case parser::OmpMapType::Value::Release: - ompFlag = Symbol::Flag::OmpMapRelease; + case parser::OmpMapType::Value::Storage: + ompFlag = Symbol::Flag::OmpMapStorage; break; case parser::OmpMapType::Value::Delete: ompFlag = Symbol::Flag::OmpMapDelete; break; } } + if (!ompFlag) { + if (version >= 60) { + // [6.0:275:12-15] + // When a map-type is not specified for a clause on which it may be + // specified, the map-type defaults to storage if the delete-modifier + // is present on the clause or if the list item for which the map-type + // is not specified is an assumed-size array. + if (OmpGetUniqueModifier(mods)) { + ompFlag = Symbol::Flag::OmpMapStorage; + } + // Otherwise, if delete-modifier is absent, leave ompFlag unset. + } else { + // [5.2:151:10] + // If a map-type is not specified, the map-type defaults to tofrom. + ompFlag = Symbol::Flag::OmpMapToFrom; + } + } + const auto &ompObjList{std::get(x.t)}; for (const auto &ompObj : ompObjList.v) { common::visit( @@ -744,15 +778,15 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor { if (const auto *name{ semantics::getDesignatorNameIfDataRef(designator)}) { if (name->symbol) { - name->symbol->set(ompFlag); - AddToContextObjectWithDSA(*name->symbol, ompFlag); - } - if (name->symbol && - semantics::IsAssumedSizeArray(*name->symbol)) { - context_.Say(designator.source, - "Assumed-size whole arrays may not appear on the %s " - "clause"_err_en_US, - "MAP"); + name->symbol->set( + ompFlag.value_or(Symbol::Flag::OmpMapStorage)); + AddToContextObjectWithDSA(*name->symbol, *ompFlag); + if (semantics::IsAssumedSizeArray(*name->symbol)) { + context_.Say(designator.source, + "Assumed-size whole arrays may not appear on the %s " + "clause"_err_en_US, + "MAP"); + } } } }, @@ -760,7 +794,7 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor { }, ompObj.u); - ResolveOmpObject(ompObj, ompFlag); + ResolveOmpObject(ompObj, ompFlag.value_or(Symbol::Flag::OmpMapStorage)); } } @@ -2759,9 +2793,8 @@ void OmpAttributeVisitor::ResolveOmpObject( } Symbol::Flag dataMappingAttributeFlags[] = { Symbol::Flag::OmpMapTo, Symbol::Flag::OmpMapFrom, - Symbol::Flag::OmpMapToFrom, Symbol::Flag::OmpMapAlloc, - Symbol::Flag::OmpMapRelease, Symbol::Flag::OmpMapDelete, - Symbol::Flag::OmpIsDevicePtr, + Symbol::Flag::OmpMapToFrom, Symbol::Flag::OmpMapStorage, + Symbol::Flag::OmpMapDelete, Symbol::Flag::OmpIsDevicePtr, Symbol::Flag::OmpHasDeviceAddr}; Symbol::Flag dataSharingAttributeFlags[] = { diff --git a/flang/lib/Semantics/resolve-labels.cpp b/flang/lib/Semantics/resolve-labels.cpp index b0cbc4b56e889..9454ef9fe928a 100644 --- a/flang/lib/Semantics/resolve-labels.cpp +++ b/flang/lib/Semantics/resolve-labels.cpp @@ -489,15 +489,29 @@ class ParseTreeAnalyzer { // C1401 void Post(const parser::MainProgram &mainProgram) { + // Uppercase the name of the main program, so that its symbol name + // would be unique from similarly named non-main-program symbols. + auto upperCaseCharBlock = [](const parser::CharBlock &cb) { + auto ch{const_cast(cb.begin())}; + for (char *endCh{ch + cb.size()}; ch != endCh; ++ch) { + *ch = parser::ToUpperCaseLetter(*ch); + } + }; + const parser::CharBlock *progName{nullptr}; + if (const auto &program{ + std::get>>( + mainProgram.t)}) { + progName = &program->statement.v.source; + upperCaseCharBlock(*progName); + } if (const parser::CharBlock * endName{GetStmtName(std::get>( mainProgram.t))}) { - if (const auto &program{ - std::get>>( - mainProgram.t)}) { - if (*endName != program->statement.v.source) { + upperCaseCharBlock(*endName); + if (progName) { + if (*endName != *progName) { context_.Say(*endName, "END PROGRAM name mismatch"_err_en_US) - .Attach(program->statement.v.source, "should be"_en_US); + .Attach(*progName, "should be"_en_US); } } else { context_.Say(*endName, diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 96faa5fd954cd..b3268605e7c0c 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -8574,8 +8574,10 @@ bool ResolveNamesVisitor::Pre(const parser::ImportStmt &x) { } else { Say(name, "A distinct '%s' is already present in this scope"_err_en_US) - .Attach(symbol->name(), "Previous declaration of '%s'"_en_US) - .Attach(outer->name(), "Declaration of '%s' in host scope"_en_US); + .Attach(symbol->name(), "Previous declaration of '%s'"_en_US, + symbol->name().ToString()) + .Attach(outer->name(), "Declaration of '%s' in host scope"_en_US, + outer->name().ToString()); } } } else { diff --git a/flang/lib/Semantics/runtime-type-info.cpp b/flang/lib/Semantics/runtime-type-info.cpp index 51ba21a9e5edf..5916a07df7744 100644 --- a/flang/lib/Semantics/runtime-type-info.cpp +++ b/flang/lib/Semantics/runtime-type-info.cpp @@ -1131,7 +1131,7 @@ void RuntimeTableBuilder::DescribeSpecialProc( if (auto proc{evaluate::characteristics::Procedure::Characterize( specific, context_.foldingContext())}) { std::uint8_t isArgDescriptorSet{0}; - std::uint8_t isArgContiguousSet{0}; + bool specialCaseFlag{0}; int argThatMightBeDescriptor{0}; MaybeExpr which; if (isAssignment) { @@ -1197,7 +1197,7 @@ void RuntimeTableBuilder::DescribeSpecialProc( TypeAndShape::Attr::AssumedShape) || dummyData.attrs.test(evaluate::characteristics:: DummyDataObject::Attr::Contiguous)) { - isArgContiguousSet |= 1; + specialCaseFlag = true; } } } @@ -1216,7 +1216,7 @@ void RuntimeTableBuilder::DescribeSpecialProc( return; } if (ddo->type.type().IsPolymorphic()) { - isArgDescriptorSet |= 1; + argThatMightBeDescriptor = 1; } switch (io.value()) { case common::DefinedIo::ReadFormatted: @@ -1232,6 +1232,9 @@ void RuntimeTableBuilder::DescribeSpecialProc( which = writeUnformattedEnum_; break; } + if (context_.defaultKinds().GetDefaultKind(TypeCategory::Integer) == 8) { + specialCaseFlag = true; // UNIT= & IOSTAT= INTEGER(8) + } } if (argThatMightBeDescriptor != 0) { if (const auto *dummyData{ @@ -1262,8 +1265,8 @@ void RuntimeTableBuilder::DescribeSpecialProc( } CHECK(bindingIndex <= 255); AddValue(values, specialSchema_, "istypebound"s, IntExpr<1>(bindingIndex)); - AddValue(values, specialSchema_, "isargcontiguousset"s, - IntExpr<1>(isArgContiguousSet)); + AddValue(values, specialSchema_, "specialcaseflag"s, + IntExpr<1>(specialCaseFlag)); AddValue(values, specialSchema_, procCompName, SomeExpr{evaluate::ProcedureDesignator{specific}}); // index might already be present in the case of an override @@ -1383,19 +1386,26 @@ CollectNonTbpDefinedIoGenericInterfaces( } else { // Local scope's specific overrides host's for this type bool updated{false}; + std::uint8_t flags{0}; + if (declType->IsPolymorphic()) { + flags |= IsDtvArgPolymorphic; + } + if (scope.context().GetDefaultKind(TypeCategory::Integer) == + 8) { + flags |= DefinedIoInteger8; + } for (auto [iter, end]{result.equal_range(dtDesc)}; iter != end; ++iter) { NonTbpDefinedIo &nonTbp{iter->second}; if (nonTbp.definedIo == which) { nonTbp.subroutine = &*specific; - nonTbp.isDtvArgPolymorphic = declType->IsPolymorphic(); + nonTbp.flags = flags; updated = true; } } if (!updated) { - result.emplace(dtDesc, - NonTbpDefinedIo{ - &*specific, which, declType->IsPolymorphic()}); + result.emplace( + dtDesc, NonTbpDefinedIo{&*specific, which, flags}); } } } diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp index ab78605d01f4c..6db11aaf56c2a 100644 --- a/flang/lib/Semantics/semantics.cpp +++ b/flang/lib/Semantics/semantics.cpp @@ -376,8 +376,7 @@ const DeclTypeSpec &SemanticsContext::MakeLogicalType(int kind) { } bool SemanticsContext::AnyFatalError() const { - return !messages_.empty() && - (warningsAreErrors_ || messages_.AnyFatalError()); + return messages_.AnyFatalError(warningsAreErrors_); } bool SemanticsContext::HasError(const Symbol &symbol) { return errorSymbols_.count(symbol) > 0; @@ -643,8 +642,7 @@ bool Semantics::Perform() { return ValidateLabels(context_, program_) && parser::CanonicalizeDo(program_) && // force line break CanonicalizeAcc(context_.messages(), program_) && - CanonicalizeOmp(context_.messages(), program_) && - CanonicalizeCUDA(program_) && + CanonicalizeOmp(context_, program_) && CanonicalizeCUDA(program_) && PerformStatementSemantics(context_, program_) && CanonicalizeDirectives(context_.messages(), program_) && ModFileWriter{context_} @@ -658,7 +656,7 @@ void Semantics::EmitMessages(llvm::raw_ostream &os) { context_.messages().ResolveProvenances(context_.allCookedSources()); context_.messages().Emit(os, context_.allCookedSources(), /*echoSourceLine=*/true, &context_.languageFeatures(), - /*maxErrorsToEmit=*/context_.maxErrors()); + context_.maxErrors(), context_.warningsAreErrors()); } void SemanticsContext::DumpSymbols(llvm::raw_ostream &os) { diff --git a/flang/lib/Semantics/symbol.cpp b/flang/lib/Semantics/symbol.cpp index 0380207927ad3..2259cfcf23ece 100644 --- a/flang/lib/Semantics/symbol.cpp +++ b/flang/lib/Semantics/symbol.cpp @@ -861,8 +861,7 @@ std::string Symbol::OmpFlagToClauseName(Symbol::Flag ompFlag) { case Symbol::Flag::OmpMapTo: case Symbol::Flag::OmpMapFrom: case Symbol::Flag::OmpMapToFrom: - case Symbol::Flag::OmpMapAlloc: - case Symbol::Flag::OmpMapRelease: + case Symbol::Flag::OmpMapStorage: case Symbol::Flag::OmpMapDelete: clauseName = "MAP"; break; diff --git a/flang/lib/Semantics/tools.cpp b/flang/lib/Semantics/tools.cpp index 5e5b43f26c791..5a5b02e1ac3ce 100644 --- a/flang/lib/Semantics/tools.cpp +++ b/flang/lib/Semantics/tools.cpp @@ -348,9 +348,9 @@ const Symbol &BypassGeneric(const Symbol &symbol) { const Symbol &GetCrayPointer(const Symbol &crayPointee) { const Symbol *found{nullptr}; - for (const auto &[pointee, pointer] : - crayPointee.GetUltimate().owner().crayPointers()) { - if (pointee == crayPointee.name()) { + const Symbol &ultimate{crayPointee.GetUltimate()}; + for (const auto &[pointee, pointer] : ultimate.owner().crayPointers()) { + if (pointee == ultimate.name()) { found = &pointer.get(); break; } diff --git a/flang/module/__fortran_type_info.f90 b/flang/module/__fortran_type_info.f90 index 8dd27d6e4c01b..6af2a5a5e30ff 100644 --- a/flang/module/__fortran_type_info.f90 +++ b/flang/module/__fortran_type_info.f90 @@ -118,7 +118,7 @@ integer(1) :: which ! SpecialBinding::Which integer(1) :: isArgDescriptorSet integer(1) :: isTypeBound ! binding index + 1, if any - integer(1) :: isArgContiguousSet + integer(1) :: specialCaseFlag integer(1) :: __padding0(4) type(__builtin_c_funptr) :: proc end type diff --git a/flang/module/cudadevice.f90 b/flang/module/cudadevice.f90 index f8a30da8b9615..d0c312c09353f 100644 --- a/flang/module/cudadevice.f90 +++ b/flang/module/cudadevice.f90 @@ -957,11 +957,21 @@ attributes(device) pure integer function atomicxori(address, val) ! Time function + interface + attributes(device) integer function clock() + end function + end interface + interface attributes(device) integer(8) function clock64() end function end interface + interface + attributes(device) integer(8) function globalTimer() + end function + end interface + ! Warp Match Functions interface match_all_sync diff --git a/flang/test/Driver/cuda-option.f90 b/flang/test/Driver/cuda-option.f90 index 0740ed509a077..f55e88dab20ce 100644 --- a/flang/test/Driver/cuda-option.f90 +++ b/flang/test/Driver/cuda-option.f90 @@ -8,7 +8,7 @@ program main integer, device :: dvar end program -! CHECK-LABEL: PROGRAM main +! CHECK-LABEL: PROGRAM MAIN ! CHECK: INTEGER :: var = 1 ! CHECK: INTEGER, DEVICE :: dvar diff --git a/flang/test/Driver/fatal-errors-warnings.f90 b/flang/test/Driver/fatal-errors-warnings.f90 new file mode 100644 index 0000000000000..2de09c3ed0778 --- /dev/null +++ b/flang/test/Driver/fatal-errors-warnings.f90 @@ -0,0 +1,31 @@ +! RUN: %flang_fc1 -Wfatal-errors -pedantic %s 2>&1 | FileCheck %s --check-prefix=CHECK1 +! RUN: not %flang_fc1 -pedantic -Werror %s 2>&1 | FileCheck %s --check-prefix=CHECK2 +! RUN: not %flang_fc1 -Wfatal-errors -pedantic -Werror %s 2>&1 | FileCheck %s --check-prefix=CHECK3 + +module m + contains + subroutine foo(a) + real, intent(in), target :: a(:) + end subroutine +end module + +program test + use m + real, target :: a(1) + real :: b(1) + call foo(a) ! ok + !CHECK1: fatal-errors-warnings.f90:{{.*}} warning: + !CHECK2: fatal-errors-warnings.f90:{{.*}} warning: + !CHECK3: fatal-errors-warnings.f90:{{.*}} warning: + call foo(b) + !CHECK1: fatal-errors-warnings.f90:{{.*}} warning: + !CHECK2: fatal-errors-warnings.f90:{{.*}} warning: + !CHECK3-NOT: error: + !CHECK3-NOT: warning: + call foo((a)) + !CHECK1: fatal-errors-warnings.f90:{{.*}} warning: + !CHECK2: fatal-errors-warnings.f90:{{.*}} warning: + call foo(a([1])) + !! Hard error instead of warning if uncommented. + !call foo(a(1)) +end \ No newline at end of file diff --git a/flang/test/Driver/intrinsic-module-path.f90 b/flang/test/Driver/intrinsic-module-path.f90 index 8fe486cf61c83..615d8f9a1730a 100644 --- a/flang/test/Driver/intrinsic-module-path.f90 +++ b/flang/test/Driver/intrinsic-module-path.f90 @@ -8,6 +8,7 @@ !----------------------------------------- ! RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s --allow-empty --check-prefix=WITHOUT ! RUN: not %flang_fc1 -fsyntax-only -fintrinsic-modules-path %S/Inputs/ %s 2>&1 | FileCheck %s --check-prefix=GIVEN +! RUN: not %flang_fc1 -fsyntax-only -fintrinsic-modules-path=%S/Inputs/ %s 2>&1 | FileCheck %s --check-prefix=GIVEN ! WITHOUT-NOT: 'ieee_arithmetic.mod' was not found ! WITHOUT-NOT: 'iso_fortran_env.mod' was not found diff --git a/flang/test/Driver/target-cpu-features.f90 b/flang/test/Driver/target-cpu-features.f90 index 5a3fd0d838002..e7da964184c85 100644 --- a/flang/test/Driver/target-cpu-features.f90 +++ b/flang/test/Driver/target-cpu-features.f90 @@ -44,6 +44,10 @@ ! RUN: %flang --target=loongarch64-linux-gnu -c %s -### 2>&1 \ ! RUN: | FileCheck %s -check-prefix=CHECK-LOONGARCH64 +! RUN: %flang --target=sparc64-linux-gnu -c -### %s 2>&1 | FileCheck %s -check-prefix=CHECK-SPARC-VIS +! RUN: %flang --target=sparc64-freebsd -c -### %s 2>&1 | FileCheck %s -check-prefix=CHECK-SPARC-VIS +! RUN: %flang --target=sparc64-openbsd -c -### %s 2>&1 | FileCheck %s -check-prefix=CHECK-SPARC-VIS + ! CHECK-A57: "-fc1" "-triple" "aarch64-unknown-linux-gnu" ! CHECK-A57-SAME: "-target-cpu" "cortex-a57" ! CHECK-A57-SAME: "-target-feature" "+v8a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+perfmon" "-target-feature" "+sha2 @@ -92,3 +96,6 @@ ! CHECK-LOONGARCH64: "-fc1" "-triple" "loongarch64-unknown-linux-gnu" ! CHECK-LOONGARCH64-SAME: "-target-cpu" "loongarch64" "-target-feature" "+lsx" "-target-feature" "+64bit" "-target-feature" "+f" "-target-feature" "+d" "-target-feature" "+ual" + +! CHECK-SPARC-VIS: "-fc1" "-triple" "sparc64-{{[^"]+}}" +! CHECK-SPARC-VIS-SAME: "-target-feature" "+vis" diff --git a/flang/test/Driver/unparse-use-analyzed.f95 b/flang/test/Driver/unparse-use-analyzed.f95 index eb6046aebba54..4bcd72c9a5f50 100644 --- a/flang/test/Driver/unparse-use-analyzed.f95 +++ b/flang/test/Driver/unparse-use-analyzed.f95 @@ -6,12 +6,12 @@ ! RUN: %flang_fc1 -fdebug-unparse %s | FileCheck %s --check-prefix=DEFAULT ! RUN: %flang_fc1 -fdebug-unparse -fno-analyzed-objects-for-unparse %s | FileCheck %s --check-prefix=DISABLED -! DEFAULT: PROGRAM test +! DEFAULT: PROGRAM TEST ! DEFAULT-NEXT: REAL, PARAMETER :: val = 3.43e2_4 ! DEFAULT-NEXT: PRINT *, 3.47e2_4 ! DEFAULT-NEXT: END PROGRAM -! DISABLED: PROGRAM test +! DISABLED: PROGRAM TEST ! DISABLED-NEXT: REAL, PARAMETER :: val = 343.0 ! DISABLED-NEXT: PRINT *, val+4 ! DISABLED-NEXT: END PROGRAM diff --git a/flang/test/Driver/unparse-with-modules.f90 b/flang/test/Driver/unparse-with-modules.f90 index 53997f7804efa..f6444afbe47c1 100644 --- a/flang/test/Driver/unparse-with-modules.f90 +++ b/flang/test/Driver/unparse-with-modules.f90 @@ -25,7 +25,7 @@ program test !CHECK: implicit none !CHECK: real(kind=real32) x !CHECK: end module -!CHECK: program test +!CHECK: program TEST !CHECK: use :: m1 !CHECK: use :: basictestmoduletwo !CHECK: implicit none diff --git a/flang/test/Fir/CUDA/cuda-device-global.f90 b/flang/test/Fir/CUDA/cuda-device-global.f90 index 4c634513745fd..35c025dad3000 100644 --- a/flang/test/Fir/CUDA/cuda-device-global.f90 +++ b/flang/test/Fir/CUDA/cuda-device-global.f90 @@ -24,3 +24,26 @@ module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", gpu.conta // CHECK: gpu.module @cuda_device_mod // CHECK-DAG: fir.global @_QMm2ECc // CHECK-DAG: fir.global @_QMm1ECb + +// ----- + +module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", gpu.container_module} { + fir.global @_QMmEddarrays {data_attr = #cuf.cuda} : !fir.box>>,phi_i:!fir.box>>,phi0_r:!fir.box>>,phi0_i:!fir.box>>,buf_r:!fir.box>>,buf_i:!fir.box>>}>>>> { + %c0 = arith.constant 0 : index + %0 = fir.zero_bits !fir.heap>>,phi_i:!fir.box>>,phi0_r:!fir.box>>,phi0_i:!fir.box>>,buf_r:!fir.box>>,buf_i:!fir.box>>}>>> + %1 = fir.shape %c0 : (index) -> !fir.shape<1> + %2 = fir.embox %0(%1) {allocator_idx = 3 : i32} : (!fir.heap>>,phi_i:!fir.box>>,phi0_r:!fir.box>>,phi0_i:!fir.box>>,buf_r:!fir.box>>,buf_i:!fir.box>>}>>>, !fir.shape<1>) -> !fir.box>>,phi_i:!fir.box>>,phi0_r:!fir.box>>,phi0_i:!fir.box>>,buf_r:!fir.box>>,buf_i:!fir.box>>}>>>> + fir.has_value %2 : !fir.box>>,phi_i:!fir.box>>,phi0_r:!fir.box>>,phi0_i:!fir.box>>,buf_r:!fir.box>>,buf_i:!fir.box>>}>>>> + } + fir.global linkonce_odr @_QMmE.dt.devicearrays constant target : !fir.type<_QM__fortran_type_infoTderivedtype{binding:!fir.box,name:!fir.box>>}>>>>,name:!fir.box>>,sizeinbytes:i64,uninstantiated:!fir.box>>,kindparameter:!fir.box>>,lenparameterkind:!fir.box>>,component:!fir.box>>,genre:i8,category:i8,kind:i8,rank:i8,__padding0:!fir.array<4xi8>,offset:i64,characterlen:!fir.type<_QM__fortran_type_infoTvalue{genre:i8,__padding0:!fir.array<7xi8>,value:i64}>,derived:!fir.box>>,lenvalue:!fir.box,value:i64}>>>>,bounds:!fir.box,value:i64}>>>>,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>>>,procptr:!fir.box>>,offset:i64,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,special:!fir.box,proc:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,specialbitset:i32,hasparent:i8,noinitializationneeded:i8,nodestructionneeded:i8,nofinalizationneeded:i8,nodefinedassignment:i8,__padding0:!fir.array<3xi8>}> { + %0 = fir.undefined !fir.type<_QM__fortran_type_infoTderivedtype{binding:!fir.box,name:!fir.box>>}>>>>,name:!fir.box>>,sizeinbytes:i64,uninstantiated:!fir.box>>,kindparameter:!fir.box>>,lenparameterkind:!fir.box>>,component:!fir.box>>,genre:i8,category:i8,kind:i8,rank:i8,__padding0:!fir.array<4xi8>,offset:i64,characterlen:!fir.type<_QM__fortran_type_infoTvalue{genre:i8,__padding0:!fir.array<7xi8>,value:i64}>,derived:!fir.box>>,lenvalue:!fir.box,value:i64}>>>>,bounds:!fir.box,value:i64}>>>>,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>>>,procptr:!fir.box>>,offset:i64,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,special:!fir.box,proc:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,specialbitset:i32,hasparent:i8,noinitializationneeded:i8,nodestructionneeded:i8,nofinalizationneeded:i8,nodefinedassignment:i8,__padding0:!fir.array<3xi8>}> + fir.has_value %0 : !fir.type<_QM__fortran_type_infoTderivedtype{binding:!fir.box,name:!fir.box>>}>>>>,name:!fir.box>>,sizeinbytes:i64,uninstantiated:!fir.box>>,kindparameter:!fir.box>>,lenparameterkind:!fir.box>>,component:!fir.box>>,genre:i8,category:i8,kind:i8,rank:i8,__padding0:!fir.array<4xi8>,offset:i64,characterlen:!fir.type<_QM__fortran_type_infoTvalue{genre:i8,__padding0:!fir.array<7xi8>,value:i64}>,derived:!fir.box>>,lenvalue:!fir.box,value:i64}>>>>,bounds:!fir.box,value:i64}>>>>,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>>>,procptr:!fir.box>>,offset:i64,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,special:!fir.box,proc:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,specialbitset:i32,hasparent:i8,noinitializationneeded:i8,nodestructionneeded:i8,nofinalizationneeded:i8,nodefinedassignment:i8,__padding0:!fir.array<3xi8>}> + } +} + + +// CHECK-NAG: fir.global @_QMmEddarrays +// CHECK-NAG: fir.global linkonce_odr @_QMmE.dt.devicearrays +// CHECK: gpu.module @cuda_device_mod +// CHECK-NAG: fir.global @_QMmEddarrays +// CHECK-NAG: fir.global linkonce_odr @_QMmE.dt.devicearrays diff --git a/flang/test/Fir/alloc-32.fir b/flang/test/Fir/alloc-32.fir index 3eefc3225fac7..a3cbf200c24fc 100644 --- a/flang/test/Fir/alloc-32.fir +++ b/flang/test/Fir/alloc-32.fir @@ -20,7 +20,9 @@ func.func @allocmem_scalar_nonchar() -> !fir.heap { // CHECK-SAME: i32 %[[len:.*]]) // CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64 // CHECK: %[[mul2:.*]] = mul i64 1, %[[mul1]] -// CHECK: %[[trunc:.*]] = trunc i64 %[[mul2]] to i32 +// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[mul2]], 0 +// CHECK: %[[sz:.*]] = select i1 %[[cmp]], i64 %[[mul2]], i64 1 +// CHECK: %[[trunc:.*]] = trunc i64 %[[sz]] to i32 // CHECK: call ptr @malloc(i32 %[[trunc]]) func.func @allocmem_scalar_dynchar(%l : i32) -> !fir.heap> { %1 = fir.allocmem !fir.char<1,?>(%l : i32) diff --git a/flang/test/Fir/alloc.fir b/flang/test/Fir/alloc.fir index 5b4930bb9cb34..8da8b828c18b9 100644 --- a/flang/test/Fir/alloc.fir +++ b/flang/test/Fir/alloc.fir @@ -87,7 +87,9 @@ func.func @alloca_scalar_dynchar_kind(%l : i32) -> !fir.ref> { // CHECK-SAME: i32 %[[len:.*]]) // CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64 // CHECK: %[[mul2:.*]] = mul i64 1, %[[mul1]] -// CHECK: call ptr @malloc(i64 %[[mul2]]) +// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[mul2]], 0 +// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[mul2]], i64 1 +// CHECK: call ptr @malloc(i64 %[[size]]) func.func @allocmem_scalar_dynchar(%l : i32) -> !fir.heap> { %1 = fir.allocmem !fir.char<1,?>(%l : i32) return %1 : !fir.heap> @@ -97,7 +99,9 @@ func.func @allocmem_scalar_dynchar(%l : i32) -> !fir.heap> { // CHECK-SAME: i32 %[[len:.*]]) // CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64 // CHECK: %[[mul2:.*]] = mul i64 2, %[[mul1]] -// CHECK: call ptr @malloc(i64 %[[mul2]]) +// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[mul2]], 0 +// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[mul2]], i64 1 +// CHECK: call ptr @malloc(i64 %[[size]]) func.func @allocmem_scalar_dynchar_kind(%l : i32) -> !fir.heap>{ %1 = fir.allocmem !fir.char<2,?>(%l : i32) return %1 : !fir.heap> @@ -152,7 +156,9 @@ func.func @allocmem_array_of_char() -> !fir.heap> // CHECK-SAME: i32 %[[len:.*]]) // CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64 // CHECK: %[[mul2:.*]] = mul i64 9, %[[mul1]] -// CHECK: call ptr @malloc(i64 %[[mul2]]) +// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[mul2]], 0 +// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[mul2]], i64 1 +// CHECK: call ptr @malloc(i64 %[[size]]) func.func @allocmem_array_of_dynchar(%l: i32) -> !fir.heap>> { %1 = fir.allocmem !fir.array<3x3x!fir.char<1,?>>(%l : i32) return %1 : !fir.heap>> @@ -180,7 +186,9 @@ func.func @alloca_dynarray_of_nonchar2(%e: index) -> !fir.ref !fir.heap> { %1 = fir.allocmem !fir.array<3x?xi32>, %e return %1 : !fir.heap> @@ -190,7 +198,9 @@ func.func @allocmem_dynarray_of_nonchar(%e: index) -> !fir.heap !fir.heap> { %1 = fir.allocmem !fir.array, %e, %e return %1 : !fir.heap> @@ -218,7 +228,9 @@ func.func @alloca_dynarray_of_char2(%e : index) -> !fir.ref !fir.heap>> { %1 = fir.allocmem !fir.array<3x?x!fir.char<2,10>>, %e return %1 : !fir.heap>> @@ -228,7 +240,9 @@ func.func @allocmem_dynarray_of_char(%e : index) -> !fir.heap !fir.heap>> { %1 = fir.allocmem !fir.array>, %e, %e return %1 : !fir.heap>> @@ -261,7 +275,9 @@ func.func @alloca_dynarray_of_dynchar2(%l: i32, %e : index) -> !fir.ref !fir.heap>> { %1 = fir.allocmem !fir.array<3x?x!fir.char<2,?>>(%l : i32), %e return %1 : !fir.heap>> @@ -273,7 +289,9 @@ func.func @allocmem_dynarray_of_dynchar(%l: i32, %e : index) -> !fir.heap !fir.heap>> { %1 = fir.allocmem !fir.array>(%l : i32), %e, %e return %1 : !fir.heap>> @@ -312,7 +330,9 @@ func.func @alloca_array_with_holes_dynchar(%arg0: index, %arg1: index) -> !fir.r // CHECK-SAME: i64 %[[e1:.*]], i64 %[[e2:.*]]) // CHECK: %[[a:.*]] = mul i64 240, %[[e1]] // CHECK: %[[b:.*]] = mul i64 %3, %[[e2]] -// CHECK: call ptr @malloc(i64 %[[b]]) +// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[b]], 0 +// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[b]], i64 1 +// CHECK: call ptr @malloc(i64 %[[size]]) func.func @allocmem_array_with_holes_nonchar(%0 : index, %1 : index) -> !fir.heap> { %a = fir.allocmem !fir.array<4x?x3x?x5xi32>, %0, %1 return %a : !fir.heap> @@ -321,7 +341,9 @@ func.func @allocmem_array_with_holes_nonchar(%0 : index, %1 : index) -> !fir.hea // CHECK-LABEL: define ptr @allocmem_array_with_holes_char( // CHECK-SAME: i64 %[[e:.*]]) // CHECK: %[[mul:.*]] = mul i64 240, %[[e]] -// CHECK: call ptr @malloc(i64 %[[mul]]) +// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[mul]], 0 +// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[mul]], i64 1 +// CHECK: call ptr @malloc(i64 %[[size]]) func.func @allocmem_array_with_holes_char(%e: index) -> !fir.heap>> { %1 = fir.allocmem !fir.array<3x?x4x!fir.char<2,10>>, %e return %1 : !fir.heap>> @@ -331,7 +353,9 @@ func.func @allocmem_array_with_holes_char(%e: index) -> !fir.heap !fir.heap>> { %1 = fir.allocmem !fir.array<3x?x4x!fir.char<2,?>>(%arg0 : index), %arg1 return %1 : !fir.heap>> diff --git a/flang/test/Fir/arrexp.fir b/flang/test/Fir/arrexp.fir index 6c7f71f6f1f9c..e8ec8ac79e0c2 100644 --- a/flang/test/Fir/arrexp.fir +++ b/flang/test/Fir/arrexp.fir @@ -146,7 +146,9 @@ func.func @f6(%arg0: !fir.box>, %arg1: f32) { // CHECK: %[[EXT_GEP:.*]] = getelementptr {{.*}} %[[A]], i32 0, i32 7, i64 0, i32 1 // CHECK: %[[EXTENT:.*]] = load i64, ptr %[[EXT_GEP]] // CHECK: %[[SIZE:.*]] = mul i64 4, %[[EXTENT]] - // CHECK: %[[MALLOC:.*]] = call ptr @malloc(i64 %[[SIZE]]) + // CHECK: %[[CMP:.*]] = icmp sgt i64 %[[SIZE]], 0 + // CHECK: %[[SZ:.*]] = select i1 %[[CMP]], i64 %[[SIZE]], i64 1 + // CHECK: %[[MALLOC:.*]] = call ptr @malloc(i64 %[[SZ]]) %1 = fir.slice %c2, %c10, %c1 : (index, index, index) -> !fir.slice<1> %2 = fir.array_load %arg0 [%1] : (!fir.box>, !fir.slice<1>) -> !fir.array %3 = fir.slice %c1, %c9, %c1 : (index, index, index) -> !fir.slice<1> diff --git a/flang/test/Fir/convert-to-llvm.fir b/flang/test/Fir/convert-to-llvm.fir index 0e2bfe48a807d..50a98466f0d4b 100644 --- a/flang/test/Fir/convert-to-llvm.fir +++ b/flang/test/Fir/convert-to-llvm.fir @@ -216,10 +216,14 @@ func.func @test_alloc_and_freemem_one() { } // CHECK-LABEL: llvm.func @test_alloc_and_freemem_one() { -// CHECK: %[[N:.*]] = llvm.mlir.constant(4 : i64) : i64 -// CHECK-NEXT: llvm.call @malloc(%[[N]]) -// CHECK: llvm.call @free(%{{.*}}) -// CHECK-NEXT: llvm.return +// CHECK-DAG: %[[N:.*]] = llvm.mlir.constant(4 : i64) : i64 +// CHECK-DAG: %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64 +// CHECK-DAG: %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64 +// CHECK-NEXT: %[[CMP:.*]] = llvm.icmp "sgt" %[[N]], %[[ZERO]] : i64 +// CHECK-NEXT: %[[SZ:.*]] = llvm.select %[[CMP]], %[[N]], %[[ONE]] : i1, i64 +// CHECK-NEXT: llvm.call @malloc(%[[SZ]]) +// CHECK: llvm.call @free(%{{.*}}) +// CHECK-NEXT: llvm.return // ----- // Verify that fir.allocmem is transformed to a call to malloc @@ -233,8 +237,12 @@ func.func @test_alloc_and_freemem_several() { } // CHECK-LABEL: llvm.func @test_alloc_and_freemem_several() { -// CHECK: %[[N:.*]] = llvm.mlir.constant(400 : i64) : i64 -// CHECK: [[MALLOC:%.*]] = llvm.call @malloc(%[[N]]) +// CHECK-DAG: %[[N:.*]] = llvm.mlir.constant(400 : i64) : i64 +// CHECK-DAG: %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64 +// CHECK-DAG: %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64 +// CHECK-NEXT: %[[CMP:.*]] = llvm.icmp "sgt" %[[N]], %[[ZERO]] : i64 +// CHECK-NEXT: %[[SZ:.*]] = llvm.select %[[CMP]], %[[N]], %[[ONE]] : i1, i64 +// CHECK: [[MALLOC:%.*]] = llvm.call @malloc(%[[SZ]]) // CHECK: llvm.call @free([[MALLOC]]) // CHECK: llvm.return @@ -250,7 +258,11 @@ func.func @test_with_shape(%ncols: index, %nrows: index) { // CHECK: %[[FOUR:.*]] = llvm.mlir.constant(4 : i64) : i64 // CHECK: %[[DIM1_SIZE:.*]] = llvm.mul %[[FOUR]], %[[NCOLS]] : i64 // CHECK: %[[TOTAL_SIZE:.*]] = llvm.mul %[[DIM1_SIZE]], %[[NROWS]] : i64 -// CHECK: %[[MEM:.*]] = llvm.call @malloc(%[[TOTAL_SIZE]]) +// CHECK: %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64 +// CHECK: %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64 +// CHECK: %[[CMP:.*]] = llvm.icmp "sgt" %[[TOTAL_SIZE]], %[[ZERO]] : i64 +// CHECK: %[[SZ:.*]] = llvm.select %[[CMP]], %[[TOTAL_SIZE]], %[[ONE]] : i1, i64 +// CHECK: %[[MEM:.*]] = llvm.call @malloc(%[[SZ]]) // CHECK: llvm.call @free(%[[MEM]]) : (!llvm.ptr) -> () // CHECK: llvm.return // CHECK: } @@ -266,7 +278,11 @@ func.func @test_string_with_shape(%len: index, %nelems: index) { // CHECK: %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64 // CHECK: %[[LEN_SIZE:.*]] = llvm.mul %[[ONE]], %[[LEN]] : i64 // CHECK: %[[TOTAL_SIZE:.*]] = llvm.mul %[[LEN_SIZE]], %[[NELEMS]] : i64 -// CHECK: %[[MEM:.*]] = llvm.call @malloc(%[[TOTAL_SIZE]]) +// CHECK: %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64 +// CHECK: %[[ONEA:.*]] = llvm.mlir.constant(1 : i64) : i64 +// CHECK: %[[CMP:.*]] = llvm.icmp "sgt" %[[TOTAL_SIZE]], %[[ZERO]] : i64 +// CHECK: %[[SZ:.*]] = llvm.select %[[CMP]], %[[TOTAL_SIZE]], %[[ONEA]] : i1, i64 +// CHECK: %[[MEM:.*]] = llvm.call @malloc(%[[SZ]]) // CHECK: llvm.call @free(%[[MEM]]) : (!llvm.ptr) -> () // CHECK: llvm.return // CHECK: } diff --git a/flang/test/Integration/debug-common-block-1.f90 b/flang/test/Integration/debug-common-block-1.f90 index 18217637be0fa..77f47daea4a91 100644 --- a/flang/test/Integration/debug-common-block-1.f90 +++ b/flang/test/Integration/debug-common-block-1.f90 @@ -89,7 +89,7 @@ program test ! CHECK-DAG: ![[CBF3]] = !DICommonBlock(scope: ![[F3]], declaration: null, name: "__BLNK__"{{.*}}) ! CHECK-DAG: ![[CBAF3]] = !DICommonBlock(scope: ![[F3]], declaration: null, name: "a"{{.*}}) -! CHECK-DAG: ![[MAIN:[0-9]+]] = {{.*}}!DISubprogram(name: "test"{{.*}}) +! CHECK-DAG: ![[MAIN:[0-9]+]] = {{.*}}!DISubprogram(name: "TEST"{{.*}}) ! CHECK-DAG: ![[CBM]] = !DICommonBlock(scope: ![[MAIN]], declaration: null, name: "__BLNK__"{{.*}}) ! CHECK-DAG: ![[CBAM]] = !DICommonBlock(scope: ![[MAIN]], declaration: null, name: "a"{{.*}}) diff --git a/flang/test/Integration/debug-local-var-2.f90 b/flang/test/Integration/debug-local-var-2.f90 index b97be141cc8d0..0ddac633a5b1e 100644 --- a/flang/test/Integration/debug-local-var-2.f90 +++ b/flang/test/Integration/debug-local-var-2.f90 @@ -37,7 +37,7 @@ ! BOTH-LABEL: } program mn -! BOTH-DAG: ![[MAIN:.*]] = distinct !DISubprogram(name: "mn", {{.*}}) +! BOTH-DAG: ![[MAIN:.*]] = distinct !DISubprogram(name: "MN", {{.*}}) ! BOTH-DAG: ![[TYI32:.*]] = !DIBasicType(name: "integer", size: 32, encoding: DW_ATE_signed) ! BOTH-DAG: ![[TYI64:.*]] = !DIBasicType(name: "integer", size: 64, encoding: DW_ATE_signed) diff --git a/flang/test/Lower/CUDA/cuda-derived.cuf b/flang/test/Lower/CUDA/cuda-derived.cuf index 96250d88d81c4..d419ee074f7a0 100644 --- a/flang/test/Lower/CUDA/cuda-derived.cuf +++ b/flang/test/Lower/CUDA/cuda-derived.cuf @@ -25,6 +25,6 @@ program main type(t2) :: b end -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "main"} +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "MAIN"} ! CHECK: %{{.*}} = cuf.alloc !fir.type<_QMm1Tty_device{x:!fir.box>>}> {bindc_name = "a", data_attr = #cuf.cuda, uniq_name = "_QFEa"} ! CHECK: %{{.*}} = cuf.alloc !fir.type<_QMm1Tt2{b:!fir.type<_QMm1Tt1{a:!fir.box>>}>}> {bindc_name = "b", data_attr = #cuf.cuda, uniq_name = "_QFEb"} diff --git a/flang/test/Lower/CUDA/cuda-device-proc.cuf b/flang/test/Lower/CUDA/cuda-device-proc.cuf index 42ee7657966e2..d5e614a83b354 100644 --- a/flang/test/Lower/CUDA/cuda-device-proc.cuf +++ b/flang/test/Lower/CUDA/cuda-device-proc.cuf @@ -10,6 +10,7 @@ attributes(global) subroutine devsub() integer(4) :: ai integer(8) :: al integer(8) :: time + integer :: smalltime call syncthreads() call syncwarp(1) @@ -45,7 +46,9 @@ attributes(global) subroutine devsub() ai = atomicinc(ai, 1_4) ai = atomicdec(ai, 1_4) + smalltime = clock() time = clock64() + time = globalTimer() end ! CHECK-LABEL: func.func @_QPdevsub() attributes {cuf.proc_attr = #cuf.cuda_proc} @@ -82,7 +85,9 @@ end ! CHECK: %{{.*}} = llvm.atomicrmw uinc_wrap %{{.*}}, %{{.*}} seq_cst : !llvm.ptr, i32 ! CHECK: %{{.*}} = llvm.atomicrmw udec_wrap %{{.*}}, %{{.*}} seq_cst : !llvm.ptr, i32 -! CHECK: fir.call @llvm.nvvm.read.ptx.sreg.clock64() +! CHECK: %{{.*}} = nvvm.read.ptx.sreg.clock : i32 +! CHECK: %{{.*}} = nvvm.read.ptx.sreg.clock64 : i64 +! CHECK: %{{.*}} = nvvm.read.ptx.sreg.globaltimer : i64 subroutine host1() integer, device :: a(32) diff --git a/flang/test/Lower/CUDA/cuda-return01.cuf b/flang/test/Lower/CUDA/cuda-return01.cuf index 47e69a903efd3..ed7c640a71082 100644 --- a/flang/test/Lower/CUDA/cuda-return01.cuf +++ b/flang/test/Lower/CUDA/cuda-return01.cuf @@ -28,6 +28,6 @@ program main return end -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "main"} +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "MAIN"} ! CHECK: cuf.alloc !fir.box>> {bindc_name = "a", data_attr = #cuf.cuda, uniq_name = "_QFEa"} -> !fir.ref>>> ! CHECK-NOT: cuf.free diff --git a/flang/test/Lower/CUDA/cuda-return02.cuf b/flang/test/Lower/CUDA/cuda-return02.cuf index e450d7e796f22..e54818444e49c 100644 --- a/flang/test/Lower/CUDA/cuda-return02.cuf +++ b/flang/test/Lower/CUDA/cuda-return02.cuf @@ -13,7 +13,7 @@ program test return end -! CHECK: func.func @_QQmain() attributes {fir.bindc_name = "test"} { +! CHECK: func.func @_QQmain() attributes {fir.bindc_name = "TEST"} { ! CHECK: %[[DECL:.*]]:2 = hlfir.declare ! CHECK: cf.cond_br %{{.*}}, ^bb1, ^bb2 ! CHECK-NEXT: ^bb1: diff --git a/flang/test/Lower/CUDA/cuda-set-allocator.cuf b/flang/test/Lower/CUDA/cuda-set-allocator.cuf index ee89ea38a3fc7..e3bb181f65398 100644 --- a/flang/test/Lower/CUDA/cuda-set-allocator.cuf +++ b/flang/test/Lower/CUDA/cuda-set-allocator.cuf @@ -21,4 +21,36 @@ contains ! CHECK: %[[Z:.*]] = fir.coordinate_of %[[DT]]#0, z : (!fir.ref>>,y:i32,z:!fir.box>>}>>) -> !fir.ref>>> ! CHECK: cuf.set_allocator_idx %[[Z]] : !fir.ref>>> {data_attr = #cuf.cuda} + subroutine sub2() + type(ty_device), pointer :: d1 + end subroutine + +! CHECK-LABEL: func.func @_QMm1Psub2() +! CHECK: %[[ALLOC:.*]] = cuf.alloc !fir.box>>,y:i32,z:!fir.box>>}>>> {bindc_name = "d1", data_attr = #cuf.cuda, uniq_name = "_QMm1Fsub2Ed1"} -> !fir.ref>>,y:i32,z:!fir.box>>}>>>> +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOC]] {data_attr = #cuf.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QMm1Fsub2Ed1"} : (!fir.ref>>,y:i32,z:!fir.box>>}>>>>) -> (!fir.ref>>,y:i32,z:!fir.box>>}>>>>, !fir.ref>>,y:i32,z:!fir.box>>}>>>>) +! CHECK: %[[LOAD1:.*]] = fir.load %[[DECL]]#0 : !fir.ref>>,y:i32,z:!fir.box>>}>>>> +! CHECK: %[[ADDR1:.*]] = fir.box_addr %[[LOAD1]] : (!fir.box>>,y:i32,z:!fir.box>>}>>>) -> !fir.ptr>>,y:i32,z:!fir.box>>}>> +! CHECK: %[[DESIGNATE1:.*]] = hlfir.designate %[[ADDR1]]{"x"} : (!fir.ptr>>,y:i32,z:!fir.box>>}>>) -> !fir.ref>>> +! CHECK: cuf.set_allocator_idx %[[DESIGNATE1]] : !fir.ref>>> {data_attr = #cuf.cuda} +! CHECK: %[[LOAD2:.*]] = fir.load %[[DECL]]#0 : !fir.ref>>,y:i32,z:!fir.box>>}>>>> +! CHECK: %[[ADDR2:.*]] = fir.box_addr %[[LOAD2]] : (!fir.box>>,y:i32,z:!fir.box>>}>>>) -> !fir.ptr>>,y:i32,z:!fir.box>>}>> +! CHECK: %[[DESIGNATE2:.*]] = hlfir.designate %[[ADDR2]]{"z"} : (!fir.ptr>>,y:i32,z:!fir.box>>}>>) -> !fir.ref>>> +! CHECK: cuf.set_allocator_idx %[[DESIGNATE2]] : !fir.ref>>> {data_attr = #cuf.cuda} + + subroutine sub3() + type(ty_device), allocatable :: d1 + end subroutine + +! CHECK-LABEL: func.func @_QMm1Psub3() +! CHECK: %[[ALLOC:.*]] = cuf.alloc !fir.box>>,y:i32,z:!fir.box>>}>>> {bindc_name = "d1", data_attr = #cuf.cuda, uniq_name = "_QMm1Fsub3Ed1"} -> !fir.ref>>,y:i32,z:!fir.box>>}>>>> +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOC]] {data_attr = #cuf.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QMm1Fsub3Ed1"} : (!fir.ref>>,y:i32,z:!fir.box>>}>>>>) -> (!fir.ref>>,y:i32,z:!fir.box>>}>>>>, !fir.ref>>,y:i32,z:!fir.box>>}>>>>) +! CHECK: %[[LOAD1:.*]] = fir.load %[[DECL]]#0 : !fir.ref>>,y:i32,z:!fir.box>>}>>>> +! CHECK: %[[ADDR1:.*]] = fir.box_addr %[[LOAD1]] : (!fir.box>>,y:i32,z:!fir.box>>}>>>) -> !fir.heap>>,y:i32,z:!fir.box>>}>> +! CHECK: %[[DESIGNATE1:.*]] = hlfir.designate %[[ADDR1]]{"x"} : (!fir.heap>>,y:i32,z:!fir.box>>}>>) -> !fir.ref>>> +! CHECK: cuf.set_allocator_idx %[[DESIGNATE1]] : !fir.ref>>> {data_attr = #cuf.cuda} +! CHECK: %[[LOAD2:.*]] = fir.load %[[DECL]]#0 : !fir.ref>>,y:i32,z:!fir.box>>}>>>> +! CHECK: %[[ADDR2:.*]] = fir.box_addr %[[LOAD2]] : (!fir.box>>,y:i32,z:!fir.box>>}>>>) -> !fir.heap>>,y:i32,z:!fir.box>>}>> +! CHECK: %[[DESIGNATE2:.*]] = hlfir.designate %[[ADDR2]]{"z"} : (!fir.heap>>,y:i32,z:!fir.box>>}>>) -> !fir.ref>>> +! CHECK: cuf.set_allocator_idx %[[DESIGNATE2]] : !fir.ref>>> {data_attr = #cuf.cuda} + end module diff --git a/flang/test/Lower/HLFIR/intrinsic-subroutines.f90 b/flang/test/Lower/HLFIR/intrinsic-subroutines.f90 index 07c4f012781d4..cbc56ca1e395b 100644 --- a/flang/test/Lower/HLFIR/intrinsic-subroutines.f90 +++ b/flang/test/Lower/HLFIR/intrinsic-subroutines.f90 @@ -24,7 +24,7 @@ program main call mvbits(from, 2, 2, to, 0) if (any(to /= 5)) STOP 1 end program -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "main"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "MAIN"} { ! CHECK: %[[VAL_0:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.array<3xi32> {bindc_name = "from", uniq_name = "_QFEfrom"} ! CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_0]] : (index) -> !fir.shape<1> diff --git a/flang/test/Lower/HLFIR/procedure-pointer-component-structure-constructor.f90 b/flang/test/Lower/HLFIR/procedure-pointer-component-structure-constructor.f90 index 7b64634d10d4b..a097b1522307e 100644 --- a/flang/test/Lower/HLFIR/procedure-pointer-component-structure-constructor.f90 +++ b/flang/test/Lower/HLFIR/procedure-pointer-component-structure-constructor.f90 @@ -35,7 +35,7 @@ FUNCTION BAR() RESULT(res) END END -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "main"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "MAIN"} { ! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref) -> i32>}> ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref) -> i32>}> ! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.boxproc<(!fir.ref) -> i32> {bindc_name = "pp2", uniq_name = "_QFEpp2"} diff --git a/flang/test/Lower/Intrinsics/cospi.f90 b/flang/test/Lower/Intrinsics/cospi.f90 new file mode 100644 index 0000000000000..894002566141b --- /dev/null +++ b/flang/test/Lower/Intrinsics/cospi.f90 @@ -0,0 +1,22 @@ +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s --check-prefixes="CHECK" + +function test_real4(x) + real :: x, test_real4 + test_real4 = cospi(x) +end function + +! CHECK-LABEL: @_QPtest_real4 +! CHECK: %[[dfactor:.*]] = arith.constant 3.1415926535897931 : f64 +! CHECK: %[[factor:.*]] = fir.convert %[[dfactor]] : (f64) -> f32 +! CHECK: %[[mul:.*]] = arith.mulf %{{.*}}, %[[factor]] fastmath : f32 +! CHECK: %[[cos:.*]] = math.cos %[[mul]] fastmath : f32 + +function test_real8(x) + real(8) :: x, test_real8 + test_real8 = cospi(x) +end function + +! CHECK-LABEL: @_QPtest_real8 +! CHECK: %[[dfactor:.*]] = arith.constant 3.1415926535897931 : f64 +! CHECK: %[[mul:.*]] = arith.mulf %{{.*}}, %[[dfactor]] fastmath : f64 +! CHECK: %[[cos:.*]] = math.cos %[[mul]] fastmath : f64 diff --git a/flang/test/Lower/Intrinsics/sinpi.f90 b/flang/test/Lower/Intrinsics/sinpi.f90 new file mode 100644 index 0000000000000..38c2277892ec7 --- /dev/null +++ b/flang/test/Lower/Intrinsics/sinpi.f90 @@ -0,0 +1,22 @@ +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s --check-prefixes="CHECK" + +function test_real4(x) + real :: x, test_real4 + test_real4 = sinpi(x) +end function + +! CHECK-LABEL: @_QPtest_real4 +! CHECK: %[[dfactor:.*]] = arith.constant 3.1415926535897931 : f64 +! CHECK: %[[factor:.*]] = fir.convert %[[dfactor]] : (f64) -> f32 +! CHECK: %[[mul:.*]] = arith.mulf %{{.*}}, %[[factor]] fastmath : f32 +! CHECK: %[[sin:.*]] = math.sin %[[mul]] fastmath : f32 + +function test_real8(x) + real(8) :: x, test_real8 + test_real8 = sinpi(x) +end function + +! CHECK-LABEL: @_QPtest_real8 +! CHECK: %[[dfactor:.*]] = arith.constant 3.1415926535897931 : f64 +! CHECK: %[[mul:.*]] = arith.mulf %{{.*}}, %[[dfactor]] fastmath : f64 +! CHECK: %[[sin:.*]] = math.sin %[[mul]] fastmath : f64 diff --git a/flang/test/Lower/OpenACC/acc-atomic-read.f90 b/flang/test/Lower/OpenACC/acc-atomic-read.f90 index 639a98051e3a2..76751a0fa63a8 100644 --- a/flang/test/Lower/OpenACC/acc-atomic-read.f90 +++ b/flang/test/Lower/OpenACC/acc-atomic-read.f90 @@ -8,7 +8,7 @@ program acc_atomic_test g = h end program acc_atomic_test -! CHECK: func @_QQmain() attributes {fir.bindc_name = "acc_atomic_test"} { +! CHECK: func @_QQmain() attributes {fir.bindc_name = "ACC_ATOMIC_TEST"} { ! CHECK: %[[VAR_G:.*]] = fir.alloca f32 {bindc_name = "g", uniq_name = "_QFEg"} ! CHECK: %[[G_DECL:.*]]:2 = hlfir.declare %[[VAR_G]] {uniq_name = "_QFEg"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[VAR_H:.*]] = fir.alloca f32 {bindc_name = "h", uniq_name = "_QFEh"} diff --git a/flang/test/Lower/OpenACC/acc-atomic-write.f90 b/flang/test/Lower/OpenACC/acc-atomic-write.f90 index 3c55394021abf..e0116e3281820 100644 --- a/flang/test/Lower/OpenACC/acc-atomic-write.f90 +++ b/flang/test/Lower/OpenACC/acc-atomic-write.f90 @@ -2,7 +2,7 @@ ! This test checks the lowering of atomic write -!CHECK: func @_QQmain() attributes {fir.bindc_name = "acc_atomic_write_test"} { +!CHECK: func @_QQmain() attributes {fir.bindc_name = "ACC_ATOMIC_WRITE_TEST"} { !CHECK: %[[VAR_X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFEx"} !CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[VAR_X]] {uniq_name = "_QFEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[VAR_Y:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFEy"} diff --git a/flang/test/Lower/OpenACC/acc-host-data-unwrap-defaultbounds.f90 b/flang/test/Lower/OpenACC/acc-host-data-unwrap-defaultbounds.f90 index 164eb32a8f684..2de7cc5761a2b 100644 --- a/flang/test/Lower/OpenACC/acc-host-data-unwrap-defaultbounds.f90 +++ b/flang/test/Lower/OpenACC/acc-host-data-unwrap-defaultbounds.f90 @@ -15,15 +15,17 @@ subroutine acc_host_data() !$acc end host_data ! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) stride(%{{.*}} : index) startIdx(%{{.*}} : index) -! CHECK: %[[DA:.*]] = acc.use_device varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a"} -! CHECK: acc.host_data dataOperands(%[[DA]] : !fir.ref>) +! CHECK: %[[DA0:.*]] = acc.use_device varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a"} +! CHECK: %[[DA1:.*]] = acc.use_device varPtr(%[[DECLA]]#1 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a"} + ! CHECK: acc.host_data dataOperands(%[[DA0]], %[[DA1]] : !fir.ref>, !fir.ref>) !$acc host_data use_device(a) if_present !$acc end host_data ! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) stride(%{{.*}} : index) startIdx(%{{.*}} : index) -! CHECK: %[[DA:.*]] = acc.use_device varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a"} -! CHECK: acc.host_data dataOperands(%[[DA]] : !fir.ref>) { +! CHECK: %[[DA0:.*]] = acc.use_device varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a"} +! CHECK: %[[DA1:.*]] = acc.use_device varPtr(%[[DECLA]]#1 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a"} +! CHECK: acc.host_data dataOperands(%[[DA0]], %[[DA1]] : !fir.ref>{{.*}}) { ! CHECK: } attributes {ifPresent} !$acc host_data use_device(a) if(ifCondition) @@ -33,14 +35,14 @@ subroutine acc_host_data() ! CHECK: %[[DA:.*]] = acc.use_device varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a"} ! CHECK: %[[LOAD_IFCOND:.*]] = fir.load %[[DECLIFCOND]]#0 : !fir.ref> ! CHECK: %[[IFCOND_I1:.*]] = fir.convert %[[LOAD_IFCOND]] : (!fir.logical<4>) -> i1 -! CHECK: acc.host_data if(%[[IFCOND_I1]]) dataOperands(%[[DA]] : !fir.ref>) +! CHECK: acc.host_data if(%[[IFCOND_I1]]) dataOperands(%[[DA]]{{.*}} : !fir.ref>{{.*}}) !$acc host_data use_device(a) if(.true.) !$acc end host_data ! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) stride(%{{.*}} : index) startIdx(%{{.*}} : index) ! CHECK: %[[DA:.*]] = acc.use_device varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a"} -! CHECK: acc.host_data dataOperands(%[[DA]] : !fir.ref>) +! CHECK: acc.host_data dataOperands(%[[DA]]{{.*}} : !fir.ref>{{.*}}) !$acc host_data use_device(a) if(.false.) a = 1.0 diff --git a/flang/test/Lower/OpenACC/acc-host-data.f90 b/flang/test/Lower/OpenACC/acc-host-data.f90 index 871eabd256ca6..4d09b25b983b9 100644 --- a/flang/test/Lower/OpenACC/acc-host-data.f90 +++ b/flang/test/Lower/OpenACC/acc-host-data.f90 @@ -14,34 +14,37 @@ subroutine acc_host_data() !$acc host_data use_device(a) !$acc end host_data -! CHECK: %[[DA:.*]] = acc.use_device varPtr(%[[DECLA]]#0 : !fir.ref>) -> !fir.ref> {name = "a"} -! CHECK: acc.host_data dataOperands(%[[DA]] : !fir.ref>) +! CHECK: %[[DA0:.*]] = acc.use_device varPtr(%[[DECLA]]#0 : !fir.ref>) -> !fir.ref> {name = "a"} +! CHECK: %[[DA1:.*]] = acc.use_device varPtr(%[[DECLA]]#1 : !fir.ref>) -> !fir.ref> {name = "a"} +! CHECK: acc.host_data dataOperands(%[[DA0]], %[[DA1]] : !fir.ref>, !fir.ref>) !$acc host_data use_device(a) if_present !$acc end host_data -! CHECK: %[[DA:.*]] = acc.use_device varPtr(%[[DECLA]]#0 : !fir.ref>) -> !fir.ref> {name = "a"} -! CHECK: acc.host_data dataOperands(%[[DA]] : !fir.ref>) { +! CHECK: %[[DA0:.*]] = acc.use_device varPtr(%[[DECLA]]#0 : !fir.ref>) -> !fir.ref> {name = "a"} +! CHECK: %[[DA1:.*]] = acc.use_device varPtr(%[[DECLA]]#1 : !fir.ref>) -> !fir.ref> {name = "a"} +! CHECK: acc.host_data dataOperands(%[[DA0]], %[[DA1]] : !fir.ref>, !fir.ref>) ! CHECK: } attributes {ifPresent} - !$acc host_data use_device(a) if_present if_present + !$acc host_data use_device(a) if_present !$acc end host_data -! CHECK: acc.host_data dataOperands(%{{.*}} : !fir.ref>) { +! CHECK: acc.host_data dataOperands(%{{.*}}{{.*}} : !fir.ref>{{.*}}) { ! CHECK: } attributes {ifPresent} !$acc host_data use_device(a) if(ifCondition) !$acc end host_data -! CHECK: %[[DA:.*]] = acc.use_device varPtr(%[[DECLA]]#0 : !fir.ref>) -> !fir.ref> {name = "a"} +! CHECK: %[[DA0:.*]] = acc.use_device varPtr(%[[DECLA]]#0 : !fir.ref>) -> !fir.ref> {name = "a"} +! CHECK: %[[DA1:.*]] = acc.use_device varPtr(%[[DECLA]]#1 : !fir.ref>) -> !fir.ref> {name = "a"} ! CHECK: %[[LOAD_IFCOND:.*]] = fir.load %[[DECLIFCOND]]#0 : !fir.ref> ! CHECK: %[[IFCOND_I1:.*]] = fir.convert %[[LOAD_IFCOND]] : (!fir.logical<4>) -> i1 -! CHECK: acc.host_data if(%[[IFCOND_I1]]) dataOperands(%[[DA]] : !fir.ref>) +! CHECK: acc.host_data if(%[[IFCOND_I1]]) dataOperands(%[[DA0]]{{.*}} : !fir.ref>{{.*}}) !$acc host_data use_device(a) if(.true.) !$acc end host_data ! CHECK: %[[DA:.*]] = acc.use_device varPtr(%[[DECLA]]#0 : !fir.ref>) -> !fir.ref> {name = "a"} -! CHECK: acc.host_data dataOperands(%[[DA]] : !fir.ref>) +! CHECK: acc.host_data dataOperands(%[[DA]]{{.*}} : !fir.ref>{{.*}}) !$acc host_data use_device(a) if(.false.) a = 1.0 diff --git a/flang/test/Lower/OpenACC/acc-loop.f90 b/flang/test/Lower/OpenACC/acc-loop.f90 index c6df28ec5e000..f9f5e8c2165d5 100644 --- a/flang/test/Lower/OpenACC/acc-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-loop.f90 @@ -372,12 +372,15 @@ subroutine sub1(i, j, k) end subroutine ! CHECK: func.func @_QPsub1 -! CHECK: acc.parallel -! CHECK: %[[DC_K:.*]] = fir.alloca i32 {bindc_name = "k"} -! CHECK: %[[DC_J:.*]] = fir.alloca i32 {bindc_name = "j"} -! CHECK: %[[DC_I:.*]] = fir.alloca i32 {bindc_name = "i"} -! CHECK: %[[P_I:.*]] = acc.private varPtr(%[[DC_I]] : !fir.ref) -> !fir.ref {implicit = true, name = "i"} -! CHECK: %[[P_J:.*]] = acc.private varPtr(%[[DC_J]] : !fir.ref) -> !fir.ref {implicit = true, name = "j"} -! CHECK: %[[P_K:.*]] = acc.private varPtr(%[[DC_K]] : !fir.ref) -> !fir.ref {implicit = true, name = "k"} +! CHECK-SAME: %[[ARG_I:.*]]: !fir.ref {fir.bindc_name = "i"} +! CHECK-SAME: %[[ARG_J:.*]]: !fir.ref {fir.bindc_name = "j"} +! CHECK-SAME: %[[ARG_K:.*]]: !fir.ref {fir.bindc_name = "k"} +! CHECK: %[[DC_I:.*]]:2 = hlfir.declare %[[ARG_I]] dummy_scope %0 +! CHECK: %[[DC_J:.*]]:2 = hlfir.declare %[[ARG_J]] dummy_scope %0 +! CHECK: %[[DC_K:.*]]:2 = hlfir.declare %[[ARG_K]] dummy_scope %0 +! CHECK: acc.parallel combined(loop) +! CHECK: %[[P_I:.*]] = acc.private varPtr(%[[DC_I]]#0 : !fir.ref) -> !fir.ref {implicit = true, name = "i"} +! CHECK: %[[P_J:.*]] = acc.private varPtr(%[[DC_J]]#0 : !fir.ref) -> !fir.ref {implicit = true, name = "j"} +! CHECK: %[[P_K:.*]] = acc.private varPtr(%[[DC_K]]#0 : !fir.ref) -> !fir.ref {implicit = true, name = "k"} ! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[P_I]] : !fir.ref, @privatization_ref_i32 -> %[[P_J]] : !fir.ref, @privatization_ref_i32 -> %[[P_K]] : !fir.ref) control(%{{.*}} : i32, %{{.*}} : i32, %{{.*}} : i32) = (%c1{{.*}}, %c1{{.*}}, %c1{{.*}} : i32, i32, i32) to (%c10{{.*}}, %c100{{.*}}, %c200{{.*}} : i32, i32, i32) step (%c1{{.*}}, %c1{{.*}}, %c1{{.*}} : i32, i32, i32) ! CHECK: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} diff --git a/flang/test/Lower/OpenACC/acc-routine.f90 b/flang/test/Lower/OpenACC/acc-routine.f90 index 789f3a57e1f79..1a63b4120235c 100644 --- a/flang/test/Lower/OpenACC/acc-routine.f90 +++ b/flang/test/Lower/OpenACC/acc-routine.f90 @@ -2,13 +2,14 @@ ! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s -! CHECK: acc.routine @[[r14:.*]] func(@_QPacc_routine19) bind("_QPacc_routine17" [#acc.device_type], "_QPacc_routine17" [#acc.device_type], "_QPacc_routine16" [#acc.device_type]) -! CHECK: acc.routine @[[r13:.*]] func(@_QPacc_routine18) bind("_QPacc_routine17" [#acc.device_type], "_QPacc_routine16" [#acc.device_type]) +! CHECK: acc.routine @[[r14:.*]] func(@_QPacc_routine19) bind(@_QPacc_routine17 [#acc.device_type], @_QPacc_routine17 +! [#acc.device_type], @_QPacc_routine16 [#acc.device_type]) +! CHECK: acc.routine @[[r13:.*]] func(@_QPacc_routine18) bind(@_QPacc_routine17 [#acc.device_type], @_QPacc_routine16 [#acc.device_type]) ! CHECK: acc.routine @[[r12:.*]] func(@_QPacc_routine17) worker ([#acc.device_type]) vector ([#acc.device_type]) ! CHECK: acc.routine @[[r11:.*]] func(@_QPacc_routine16) gang([#acc.device_type]) seq ([#acc.device_type]) ! CHECK: acc.routine @[[r10:.*]] func(@_QPacc_routine11) seq ! CHECK: acc.routine @[[r09:.*]] func(@_QPacc_routine10) seq -! CHECK: acc.routine @[[r08:.*]] func(@_QPacc_routine9) bind("_QPacc_routine9a") +! CHECK: acc.routine @[[r08:.*]] func(@_QPacc_routine9) bind(@_QPacc_routine9a) ! CHECK: acc.routine @[[r07:.*]] func(@_QPacc_routine8) bind("routine8_") ! CHECK: acc.routine @[[r06:.*]] func(@_QPacc_routine7) gang(dim: 1 : i64) ! CHECK: acc.routine @[[r05:.*]] func(@_QPacc_routine6) nohost diff --git a/flang/test/Lower/OpenACC/acc-routine03.f90 b/flang/test/Lower/OpenACC/acc-routine03.f90 index 85e4ef580f983..ddd6bda0367e4 100644 --- a/flang/test/Lower/OpenACC/acc-routine03.f90 +++ b/flang/test/Lower/OpenACC/acc-routine03.f90 @@ -30,6 +30,6 @@ subroutine sub2(a) end subroutine ! CHECK: acc.routine @acc_routine_1 func(@_QPsub2) worker nohost -! CHECK: acc.routine @acc_routine_0 func(@_QPsub1) bind("_QPsub2") worker +! CHECK: acc.routine @acc_routine_0 func(@_QPsub1) bind(@_QPsub2) worker ! CHECK: func.func @_QPsub1(%arg0: !fir.box> {fir.bindc_name = "a"}) attributes {acc.routine_info = #acc.routine_info<[@acc_routine_0]>} ! CHECK: func.func @_QPsub2(%arg0: !fir.box> {fir.bindc_name = "a"}) attributes {acc.routine_info = #acc.routine_info<[@acc_routine_1]>} diff --git a/flang/test/Lower/OpenACC/acc-routine04.f90 b/flang/test/Lower/OpenACC/acc-routine04.f90 index f603376163901..655e2762b9694 100644 --- a/flang/test/Lower/OpenACC/acc-routine04.f90 +++ b/flang/test/Lower/OpenACC/acc-routine04.f90 @@ -30,5 +30,5 @@ subroutine sub2() ! CHECK: acc.routine @acc_routine_1 func(@_QFPsub2) seq ! CHECK: acc.routine @acc_routine_0 func(@_QMdummy_modPsub1) seq ! CHECK: func.func @_QMdummy_modPsub1(%arg0: !fir.ref {fir.bindc_name = "i"}) attributes {acc.routine_info = #acc.routine_info<[@acc_routine_0]>} -! CHECK: func.func @_QQmain() attributes {fir.bindc_name = "test_acc_routine"} +! CHECK: func.func @_QQmain() attributes {fir.bindc_name = "TEST_ACC_ROUTINE"} ! CHECK: func.func private @_QFPsub2() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_1]>, fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage} diff --git a/flang/test/Lower/OpenACC/acc-use-device.f90 b/flang/test/Lower/OpenACC/acc-use-device.f90 new file mode 100644 index 0000000000000..081a6e317bfc9 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-use-device.f90 @@ -0,0 +1,61 @@ +! This test checks whether the OpenACC use_device clause is applied on both results of hlfir.declare. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +! Test for automatic variable appearing in use_device clause. +subroutine test() + integer :: N = 100 + real*8 :: b(-1:N) +! CHECK: %[[A0:.*]] = fir.alloca !fir.array, %{{.*}} {bindc_name = "b", uniq_name = "_QFtestEb"} +! CHECK: %[[A1:.*]] = fir.shape_shift {{.*}} : (index, index) -> !fir.shapeshift<1> +! CHECK: %[[A:.*]]:2 = hlfir.declare %[[A0]](%[[A1]]) {uniq_name = "_QFtestEb"} : (!fir.ref>, !fir.shapeshift<1>) -> (!fir.box>, !fir.ref>) + + !$acc data copy(b) +! CHECK: %[[B:.*]] = acc.copyin var(%[[A]]#0 : !fir.box>) -> !fir.box> {dataClause = #acc, name = "b"} +! CHECK: acc.data dataOperands(%[[B]] : !fir.box>) { + + !$acc host_data use_device(b) + call vadd(b) + !$acc end host_data +! CHECK: %[[C:.*]] = acc.use_device var(%[[A]]#0 : !fir.box>) -> !fir.box> {name = "b"} +! CHECK: %[[D:.*]] = acc.use_device varPtr(%[[A]]#1 : !fir.ref>) -> !fir.ref> {name = "b"} +! CHECK: acc.host_data dataOperands(%[[C]], %[[D]] : !fir.box>, !fir.ref>) { +! CHECK: fir.call @_QPvadd(%[[A]]#1) fastmath : (!fir.ref>) -> () + !$acc end data +! CHECK: acc.copyout accVar(%[[B]] : !fir.box>) to var(%[[A]]#0 : !fir.box>) {dataClause = #acc, name = "b"} +end + +! Test for allocatable, pointer and assumed-shape variables appearing in use_device clause. +subroutine test2(a, b, c) + integer :: N = 100 + real*8, allocatable :: a(:) + real*8, target, allocatable :: d(:) + real*8 :: b(:) + real*8, pointer :: c(:) + call allocate(a(N)) + call allocate(d(N)) + c => d +! CHECK: %[[DS:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[E:.*]]:2 = hlfir.declare %arg0 dummy_scope %[[DS]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest2Ea"} : (!fir.ref>>>, !fir.dscope) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[F:.*]]:2 = hlfir.declare %arg1 dummy_scope %[[DS]] {uniq_name = "_QFtest2Eb"} : (!fir.box>, !fir.dscope) -> (!fir.box>, !fir.box>) +! CHECK: %[[G:.*]]:2 = hlfir.declare %arg2 dummy_scope %[[DS]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest2Ec"} : (!fir.ref>>>, !fir.dscope) -> (!fir.ref>>>, !fir.ref>>>) + + !$acc data copy(a,b,c,d) + !$acc host_data use_device(a,b,c) + call vadd2(a,b,c) + !$acc end host_data + +! CHECK: %[[H:.*]] = acc.use_device varPtr(%[[E]]#0 : !fir.ref>>>) -> !fir.ref>>> {name = "a"} +! CHECK: %[[I:.*]] = acc.use_device varPtr(%[[E]]#1 : !fir.ref>>>) -> !fir.ref>>> {name = "a"} +! CHECK: %[[J:.*]] = acc.use_device var(%[[F]]#0 : !fir.box>) -> !fir.box> {name = "b"} +! CHECK: %[[K:.*]] = acc.use_device var(%[[F]]#1 : !fir.box>) -> !fir.box> {name = "b"} +! CHECK: %[[L:.*]] = acc.use_device varPtr(%[[G]]#0 : !fir.ref>>>) -> !fir.ref>>> {name = "c"} +! CHECK: %[[M:.*]] = acc.use_device varPtr(%[[G]]#1 : !fir.ref>>>) -> !fir.ref>>> {name = "c"} +! CHECK: acc.host_data dataOperands(%[[H]], %[[I]], %[[J]], %[[K]], %[[L]], %[[M]] : !fir.ref>>>, !fir.ref>>>, !fir.box>, !fir.box>, !fir.ref>>>, !fir.ref>>>) { + + + + + !$acc end data + +end diff --git a/flang/test/Lower/OpenMP/atomic-read.f90 b/flang/test/Lower/OpenMP/atomic-read.f90 index 68dcaac90eef5..30313e240efa3 100644 --- a/flang/test/Lower/OpenMP/atomic-read.f90 +++ b/flang/test/Lower/OpenMP/atomic-read.f90 @@ -4,7 +4,7 @@ ! This test checks the lowering of atomic read -!CHECK: func @_QQmain() attributes {fir.bindc_name = "ompatomic"} { +!CHECK: func @_QQmain() attributes {fir.bindc_name = "OMPATOMIC"} { !CHECK: %[[A_REF:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFEa"} !CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A_REF]] {uniq_name = "_QFEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[B_REF:.*]] = fir.alloca i32 {bindc_name = "b", uniq_name = "_QFEb"} diff --git a/flang/test/Lower/OpenMP/atomic-write.f90 b/flang/test/Lower/OpenMP/atomic-write.f90 index 6eded49b0b15d..742fd475c0f04 100644 --- a/flang/test/Lower/OpenMP/atomic-write.f90 +++ b/flang/test/Lower/OpenMP/atomic-write.f90 @@ -4,7 +4,7 @@ ! This test checks the lowering of atomic write -!CHECK: func @_QQmain() attributes {fir.bindc_name = "ompatomicwrite"} { +!CHECK: func @_QQmain() attributes {fir.bindc_name = "OMPATOMICWRITE"} { !CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFEx"} !CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X_REF]] {uniq_name = "_QFEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[Y_REF:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFEy"} diff --git a/flang/test/Lower/OpenMP/common-atomic-lowering.f90 b/flang/test/Lower/OpenMP/common-atomic-lowering.f90 index a53cc101024c6..f729bbb00ac8e 100644 --- a/flang/test/Lower/OpenMP/common-atomic-lowering.f90 +++ b/flang/test/Lower/OpenMP/common-atomic-lowering.f90 @@ -1,6 +1,6 @@ !RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s -!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "sample"} { +!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "SAMPLE"} { !CHECK: %[[val_0:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFEa"} !CHECK: %[[val_1:.*]]:2 = hlfir.declare %[[val_0]] {uniq_name = "_QFEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[val_2:.*]] = fir.alloca i32 {bindc_name = "b", uniq_name = "_QFEb"} diff --git a/flang/test/Lower/OpenMP/cray-pointers02.f90 b/flang/test/Lower/OpenMP/cray-pointers02.f90 index 19e4cd09fe50a..79d838702e4b0 100644 --- a/flang/test/Lower/OpenMP/cray-pointers02.f90 +++ b/flang/test/Lower/OpenMP/cray-pointers02.f90 @@ -1,7 +1,7 @@ ! Test lowering of Cray pointee references. ! RUN: flang -fc1 -emit-hlfir -fopenmp %s -o - 2>&1 | FileCheck %s -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "test_cray_pointers_02"} +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "TEST_CRAY_POINTERS_02"} program test_cray_pointers_02 implicit none diff --git a/flang/test/Lower/OpenMP/default-clause-byref.f90 b/flang/test/Lower/OpenMP/default-clause-byref.f90 index c44c6bb966580..af51c4cc3e814 100644 --- a/flang/test/Lower/OpenMP/default-clause-byref.f90 +++ b/flang/test/Lower/OpenMP/default-clause-byref.f90 @@ -34,7 +34,7 @@ !CHECK: omp.yield(%[[PRIV_X]] : !fir.ref) !CHECK: } -!CHECK: func @_QQmain() attributes {fir.bindc_name = "default_clause_lowering"} { +!CHECK: func @_QQmain() attributes {fir.bindc_name = "DEFAULT_CLAUSE_LOWERING"} { !CHECK: %[[W:.*]] = fir.alloca i32 {bindc_name = "w", uniq_name = "_QFEw"} !CHECK: %[[W_DECL:.*]]:2 = hlfir.declare %[[W]] {uniq_name = "_QFEw"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFEx"} diff --git a/flang/test/Lower/OpenMP/default-clause.f90 b/flang/test/Lower/OpenMP/default-clause.f90 index ee5f579f06b91..505fa4f0f5d63 100644 --- a/flang/test/Lower/OpenMP/default-clause.f90 +++ b/flang/test/Lower/OpenMP/default-clause.f90 @@ -8,7 +8,7 @@ ! RUN: | FileCheck %s -!CHECK: func @_QQmain() attributes {fir.bindc_name = "default_clause_lowering"} { +!CHECK: func @_QQmain() attributes {fir.bindc_name = "DEFAULT_CLAUSE_LOWERING"} { !CHECK: %[[W:.*]] = fir.alloca i32 {bindc_name = "w", uniq_name = "_QFEw"} !CHECK: %[[W_DECL:.*]]:2 = hlfir.declare %[[W]] {uniq_name = "_QFEw"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFEx"} diff --git a/flang/test/Lower/OpenMP/map-modifiers.f90 b/flang/test/Lower/OpenMP/map-modifiers.f90 index 64d7869cbb836..be93c14627f9a 100644 --- a/flang/test/Lower/OpenMP/map-modifiers.f90 +++ b/flang/test/Lower/OpenMP/map-modifiers.f90 @@ -1,4 +1,6 @@ ! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=60 %s -o - | FileCheck %s subroutine map_present_target_data integer :: x @@ -15,6 +17,14 @@ subroutine map_present_update !$omp target update to(present: x) end subroutine +subroutine map_always + integer :: x +!CHECK: %[[MAP:.*]] = omp.map.info {{.*}} map_clauses(always, tofrom) {{.*}} {name = "x"} +!CHECK: omp.target_data map_entries(%[[MAP]] : {{.*}}) { +!$omp target data map(always, tofrom: x) +!$omp end target data +end subroutine + subroutine map_close integer :: x !CHECK: %[[MAP:.*]] = omp.map.info {{.*}} map_clauses(close, tofrom) {{.*}} {name = "x"} diff --git a/flang/test/Lower/OpenMP/nested-loop-transformation-construct01.f90 b/flang/test/Lower/OpenMP/nested-loop-transformation-construct01.f90 index a76e7e52100db..17eba93a7405d 100644 --- a/flang/test/Lower/OpenMP/nested-loop-transformation-construct01.f90 +++ b/flang/test/Lower/OpenMP/nested-loop-transformation-construct01.f90 @@ -1,6 +1,6 @@ ! Test to ensure TODO message is emitted for tile OpenMP 5.1 Directives when they are nested. -!RUN: not %flang -fopenmp -fopenmp-version=51 %s 2>&1 | FileCheck %s +!RUN: not %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s subroutine loop_transformation_construct implicit none diff --git a/flang/test/Lower/OpenMP/nested-loop-transformation-construct02.f90 b/flang/test/Lower/OpenMP/nested-loop-transformation-construct02.f90 index 33b7c5a917619..cdc628a3b2e64 100644 --- a/flang/test/Lower/OpenMP/nested-loop-transformation-construct02.f90 +++ b/flang/test/Lower/OpenMP/nested-loop-transformation-construct02.f90 @@ -1,6 +1,6 @@ ! Test to ensure TODO message is emitted for unroll OpenMP 5.1 Directives when they are nested. -!RUN: not %flang -fopenmp -fopenmp-version=51 %s 2>&1 | FileCheck %s +!RUN: not %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s program loop_transformation_construct implicit none @@ -17,4 +17,4 @@ program loop_transformation_construct !$omp end do end program loop_transformation_construct -!CHECK: not yet implemented: Unhandled loop directive (unroll) +!CHECK: not yet implemented: Applying a loop-associated on the loop generated by the unroll construct diff --git a/flang/test/Lower/OpenMP/parallel-reduction-allocatable-array.f90 b/flang/test/Lower/OpenMP/parallel-reduction-allocatable-array.f90 index 4bfd5d8d19261..0036670317a8e 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-allocatable-array.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-allocatable-array.f90 @@ -80,7 +80,7 @@ program reduce ! CHECK: omp.yield ! CHECK: } -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "REDUCE"} { ! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFEi) : !fir.ref ! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QFEr) : !fir.ref>>> diff --git a/flang/test/Lower/OpenMP/parallel-reduction-array-lb.f90 b/flang/test/Lower/OpenMP/parallel-reduction-array-lb.f90 index ec54294c7104f..ea0aa9ec3f53b 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-array-lb.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-array-lb.f90 @@ -68,7 +68,7 @@ program reduce ! CHECK: omp.yield ! CHECK: } -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "REDUCE"} { ! CHECK: %[[VAL_7:.*]] = fir.alloca !fir.box> ! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFEi) : !fir.ref> ! CHECK: %[[VAL_1:.*]] = arith.constant 2 : index diff --git a/flang/test/Lower/OpenMP/parallel-reduction-array2.f90 b/flang/test/Lower/OpenMP/parallel-reduction-array2.f90 index 488ecc353af8e..eb0df2b3a17de 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-array2.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-array2.f90 @@ -63,7 +63,7 @@ program reduce ! CHECK: omp.yield ! CHECK: } -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "REDUCE"} { ! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFEi) : !fir.ref> ! CHECK: %[[VAL_1:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1> diff --git a/flang/test/Lower/OpenMP/parallel-reduction-byref.f90 b/flang/test/Lower/OpenMP/parallel-reduction-byref.f90 index 596276a99cafc..2caec0384a6ab 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-byref.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-byref.f90 @@ -18,7 +18,7 @@ !CHECK: fir.store %[[CR]] to %[[C0]] : !fir.ref !CHECK: omp.yield(%[[C0]] : !fir.ref) !CHECK: } -!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "mn"} { +!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "MN"} { !CHECK: %[[RED_ACCUM_REF:[_a-z0-9]+]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} !CHECK: %[[RED_ACCUM_DECL:[_a-z0-9]+]]:2 = hlfir.declare %[[RED_ACCUM_REF]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[C0:[_a-z0-9]+]] = arith.constant 0 : i32 diff --git a/flang/test/Lower/OpenMP/parallel-reduction-pointer-array.f90 b/flang/test/Lower/OpenMP/parallel-reduction-pointer-array.f90 index f638688bc2cc1..3c1daa0eb983f 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-pointer-array.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-pointer-array.f90 @@ -82,7 +82,7 @@ program reduce ! CHECK: omp.yield ! CHECK: } -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "REDUCE"} { ! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFEi) : !fir.ref ! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QFEr) : !fir.ref>>> diff --git a/flang/test/Lower/OpenMP/parallel-reduction-rename.f90 b/flang/test/Lower/OpenMP/parallel-reduction-rename.f90 index c06343e997bfd..2be154f4bbaf5 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-rename.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-rename.f90 @@ -25,7 +25,7 @@ end program main ! CHECK: omp.yield(%[[VAL_2]] : i32) ! CHECK: } -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "main"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "MAIN"} { ! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "n", uniq_name = "_QFEn"} ! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFEn"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[VAL_2:.*]] = arith.constant 0 : i32 diff --git a/flang/test/Lower/OpenMP/parallel-reduction.f90 b/flang/test/Lower/OpenMP/parallel-reduction.f90 index 612549fb32de5..15e8cc325916d 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction.f90 @@ -10,7 +10,7 @@ !CHECK: %[[CR:[_a-z0-9]+]] = arith.addi %[[C0]], %[[C1]] : i32 !CHECK: omp.yield(%[[CR]] : i32) !CHECK: } -!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "mn"} { +!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "MN"} { !CHECK: %[[RED_ACCUM_REF:[_a-z0-9]+]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} !CHECK: %[[RED_ACCUM_DECL:[_a-z0-9]+]]:2 = hlfir.declare %[[RED_ACCUM_REF]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[C0:[_a-z0-9]+]] = arith.constant 0 : i32 diff --git a/flang/test/Lower/OpenMP/sections.f90 b/flang/test/Lower/OpenMP/sections.f90 index d11925cafdc12..3d5c0326fb6b9 100644 --- a/flang/test/Lower/OpenMP/sections.f90 +++ b/flang/test/Lower/OpenMP/sections.f90 @@ -5,7 +5,7 @@ ! RUN: %flang_fc1 -emit-hlfir %openmp_flags %s -o - | FileCheck %s ! RUN: bbc -hlfir -emit-hlfir %openmp_flags %s -o - | FileCheck %s -!CHECK: func @_QQmain() attributes {fir.bindc_name = "sample"} { +!CHECK: func @_QQmain() attributes {fir.bindc_name = "SAMPLE"} { !CHECK: %[[COUNT:.*]] = fir.address_of(@_QFEcount) : !fir.ref !CHECK: %[[COUNT_DECL:.*]]:2 = hlfir.declare %[[COUNT]] {uniq_name = "_QFEcount"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[ETA:.*]] = fir.alloca f32 {bindc_name = "eta", uniq_name = "_QFEeta"} diff --git a/flang/test/Lower/OpenMP/taskgroup02.f90 b/flang/test/Lower/OpenMP/taskgroup02.f90 index 1e996a030c23a..4c470b7aa82d1 100644 --- a/flang/test/Lower/OpenMP/taskgroup02.f90 +++ b/flang/test/Lower/OpenMP/taskgroup02.f90 @@ -3,8 +3,9 @@ ! Check that variables are not privatized twice when TASKGROUP is used. !CHECK-LABEL: func.func @_QPsub() { -!CHECK: omp.parallel { -!CHECK: %[[PAR_I:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFsubEi"} +!CHECK: omp.parallel private(@_QFsubEi_private_i32 %[[SUB_I:.*]]#0 -> %[[ARG:.*]] : !fir.ref) +!CHECK: %[[ALLOCA:.*]] = fir.alloca i32 +!CHECK: %[[PAR_I:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "_QFsubEi"} !CHECK: omp.master { !CHECK: omp.taskgroup { !CHECK-NEXT: omp.task private(@_QFsubEi_firstprivate_i32 %[[PAR_I]]#0 -> %[[TASK_I:.*]] : !fir.ref) { diff --git a/flang/test/Lower/OpenMP/threadprivate-host-association-2.f90 b/flang/test/Lower/OpenMP/threadprivate-host-association-2.f90 index 5e54cef8c29db..5c90ef7d84f89 100644 --- a/flang/test/Lower/OpenMP/threadprivate-host-association-2.f90 +++ b/flang/test/Lower/OpenMP/threadprivate-host-association-2.f90 @@ -3,7 +3,7 @@ !RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s -!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "main"} { +!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "MAIN"} { !CHECK: %[[A:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFEa"} !CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[A_ADDR:.*]] = fir.address_of(@_QFEa) : !fir.ref diff --git a/flang/test/Lower/OpenMP/threadprivate-host-association-3.f90 b/flang/test/Lower/OpenMP/threadprivate-host-association-3.f90 index 21547b47cf381..0e61261e8853e 100644 --- a/flang/test/Lower/OpenMP/threadprivate-host-association-3.f90 +++ b/flang/test/Lower/OpenMP/threadprivate-host-association-3.f90 @@ -3,7 +3,7 @@ !RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s -!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "main"} { +!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "MAIN"} { !CHECK: %[[A:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFEa"} !CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[A_ADDR:.*]] = fir.address_of(@_QFEa) : !fir.ref diff --git a/flang/test/Lower/OpenMP/threadprivate-host-association.f90 b/flang/test/Lower/OpenMP/threadprivate-host-association.f90 index 7a27efa2f84aa..1887e8aa68fdc 100644 --- a/flang/test/Lower/OpenMP/threadprivate-host-association.f90 +++ b/flang/test/Lower/OpenMP/threadprivate-host-association.f90 @@ -3,7 +3,7 @@ !RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s -!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "main"} { +!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "MAIN"} { !CHECK: %[[A:.*]] = fir.address_of(@_QFEa) : !fir.ref !CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_DECL]]#0 : !fir.ref -> !fir.ref diff --git a/flang/test/Lower/OpenMP/unroll-heuristic01.f90 b/flang/test/Lower/OpenMP/unroll-heuristic01.f90 new file mode 100644 index 0000000000000..a5f5c003b8a7c --- /dev/null +++ b/flang/test/Lower/OpenMP/unroll-heuristic01.f90 @@ -0,0 +1,39 @@ +! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s + + +subroutine omp_unroll_heuristic01(lb, ub, inc) + integer res, i, lb, ub, inc + + !$omp unroll + do i = lb, ub, inc + res = i + end do + !$omp end unroll + +end subroutine omp_unroll_heuristic01 + + +!CHECK-LABEL: func.func @_QPomp_unroll_heuristic01( +!CHECK: %c0_i32 = arith.constant 0 : i32 +!CHECK-NEXT: %c1_i32 = arith.constant 1 : i32 +!CHECK-NEXT: %13 = arith.cmpi slt, %12, %c0_i32 : i32 +!CHECK-NEXT: %14 = arith.subi %c0_i32, %12 : i32 +!CHECK-NEXT: %15 = arith.select %13, %14, %12 : i32 +!CHECK-NEXT: %16 = arith.select %13, %11, %10 : i32 +!CHECK-NEXT: %17 = arith.select %13, %10, %11 : i32 +!CHECK-NEXT: %18 = arith.subi %17, %16 overflow : i32 +!CHECK-NEXT: %19 = arith.divui %18, %15 : i32 +!CHECK-NEXT: %20 = arith.addi %19, %c1_i32 overflow : i32 +!CHECK-NEXT: %21 = arith.cmpi slt, %17, %16 : i32 +!CHECK-NEXT: %22 = arith.select %21, %c0_i32, %20 : i32 +!CHECK-NEXT: %canonloop_s0 = omp.new_cli +!CHECK-NEXT: omp.canonical_loop(%canonloop_s0) %iv : i32 in range(%22) { +!CHECK-NEXT: %23 = arith.muli %iv, %12 : i32 +!CHECK-NEXT: %24 = arith.addi %10, %23 : i32 +!CHECK-NEXT: hlfir.assign %24 to %9#0 : i32, !fir.ref +!CHECK-NEXT: %25 = fir.load %9#0 : !fir.ref +!CHECK-NEXT: hlfir.assign %25 to %6#0 : i32, !fir.ref +!CHECK-NEXT: omp.terminator +!CHECK-NEXT: } +!CHECK-NEXT: omp.unroll_heuristic(%canonloop_s0) +!CHECK-NEXT: return diff --git a/flang/test/Lower/OpenMP/unroll-heuristic02.f90 b/flang/test/Lower/OpenMP/unroll-heuristic02.f90 new file mode 100644 index 0000000000000..14f694d6cdb78 --- /dev/null +++ b/flang/test/Lower/OpenMP/unroll-heuristic02.f90 @@ -0,0 +1,97 @@ +! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s + + +subroutine omp_unroll_heuristic_nested02(outer_lb, outer_ub, outer_inc, inner_lb, inner_ub, inner_inc) + integer res, i, j, inner_lb, inner_ub, inner_inc, outer_lb, outer_ub, outer_inc + + !$omp unroll + do i = outer_lb, outer_ub, outer_inc + !$omp unroll + do j = inner_lb, inner_ub, inner_inc + res = i + j + end do + !$omp end unroll + end do + !$omp end unroll + +end subroutine omp_unroll_heuristic_nested02 + + +!CHECK-LABEL: func.func @_QPomp_unroll_heuristic_nested02( +!CHECK-SAME: %[[ARG0:.*]]: !fir.ref {fir.bindc_name = "outer_lb"}, +!CHECK-SAME: %[[ARG1:.*]]: !fir.ref {fir.bindc_name = "outer_ub"}, +!CHECK-SAME: %[[ARG2:.*]]: !fir.ref {fir.bindc_name = "outer_inc"}, +!CHECK-SAME: %[[ARG3:.*]]: !fir.ref {fir.bindc_name = "inner_lb"}, +!CHECK-SAME: %[[ARG4:.*]]: !fir.ref {fir.bindc_name = "inner_ub"}, +!CHECK-SAME: %[[ARG5:.*]]: !fir.ref {fir.bindc_name = "inner_inc"}) { +!CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope +!CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_unroll_heuristic_nested02Ei"} +!CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFomp_unroll_heuristic_nested02Ei"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG5]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic_nested02Einner_inc"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +!CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[ARG3]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic_nested02Einner_lb"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +!CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[ARG4]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic_nested02Einner_ub"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +!CHECK: %[[VAL_6:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFomp_unroll_heuristic_nested02Ej"} +!CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFomp_unroll_heuristic_nested02Ej"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic_nested02Eouter_inc"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +!CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic_nested02Eouter_lb"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +!CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic_nested02Eouter_ub"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +!CHECK: %[[VAL_11:.*]] = fir.alloca i32 {bindc_name = "res", uniq_name = "_QFomp_unroll_heuristic_nested02Eres"} +!CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {uniq_name = "_QFomp_unroll_heuristic_nested02Eres"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[VAL_13:.*]] = fir.alloca i32 {bindc_name = "i", pinned, uniq_name = "_QFomp_unroll_heuristic_nested02Ei"} +!CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_13]] {uniq_name = "_QFomp_unroll_heuristic_nested02Ei"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[VAL_15:.*]] = fir.alloca i32 {bindc_name = "j", pinned, uniq_name = "_QFomp_unroll_heuristic_nested02Ej"} +!CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFomp_unroll_heuristic_nested02Ej"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref +!CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_10]]#0 : !fir.ref +!CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref +!CHECK: %[[VAL_20:.*]] = arith.constant 0 : i32 +!CHECK: %[[VAL_21:.*]] = arith.constant 1 : i32 +!CHECK: %[[VAL_22:.*]] = arith.cmpi slt, %[[VAL_19]], %[[VAL_20]] : i32 +!CHECK: %[[VAL_23:.*]] = arith.subi %[[VAL_20]], %[[VAL_19]] : i32 +!CHECK: %[[VAL_24:.*]] = arith.select %[[VAL_22]], %[[VAL_23]], %[[VAL_19]] : i32 +!CHECK: %[[VAL_25:.*]] = arith.select %[[VAL_22]], %[[VAL_18]], %[[VAL_17]] : i32 +!CHECK: %[[VAL_26:.*]] = arith.select %[[VAL_22]], %[[VAL_17]], %[[VAL_18]] : i32 +!CHECK: %[[VAL_27:.*]] = arith.subi %[[VAL_26]], %[[VAL_25]] overflow : i32 +!CHECK: %[[VAL_28:.*]] = arith.divui %[[VAL_27]], %[[VAL_24]] : i32 +!CHECK: %[[VAL_29:.*]] = arith.addi %[[VAL_28]], %[[VAL_21]] overflow : i32 +!CHECK: %[[VAL_30:.*]] = arith.cmpi slt, %[[VAL_26]], %[[VAL_25]] : i32 +!CHECK: %[[VAL_31:.*]] = arith.select %[[VAL_30]], %[[VAL_20]], %[[VAL_29]] : i32 +!CHECK: %[[VAL_32:.*]] = omp.new_cli +!CHECK: omp.canonical_loop(%[[VAL_32]]) %[[VAL_33:.*]] : i32 in range(%[[VAL_31]]) { +!CHECK: %[[VAL_34:.*]] = arith.muli %[[VAL_33]], %[[VAL_19]] : i32 +!CHECK: %[[VAL_35:.*]] = arith.addi %[[VAL_17]], %[[VAL_34]] : i32 +!CHECK: hlfir.assign %[[VAL_35]] to %[[VAL_14]]#0 : i32, !fir.ref +!CHECK: %[[VAL_36:.*]] = fir.alloca i32 {bindc_name = "j", pinned, uniq_name = "_QFomp_unroll_heuristic_nested02Ej"} +!CHECK: %[[VAL_37:.*]]:2 = hlfir.declare %[[VAL_36]] {uniq_name = "_QFomp_unroll_heuristic_nested02Ej"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[VAL_38:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref +!CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref +!CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref +!CHECK: %[[VAL_41:.*]] = arith.constant 0 : i32 +!CHECK: %[[VAL_42:.*]] = arith.constant 1 : i32 +!CHECK: %[[VAL_43:.*]] = arith.cmpi slt, %[[VAL_40]], %[[VAL_41]] : i32 +!CHECK: %[[VAL_44:.*]] = arith.subi %[[VAL_41]], %[[VAL_40]] : i32 +!CHECK: %[[VAL_45:.*]] = arith.select %[[VAL_43]], %[[VAL_44]], %[[VAL_40]] : i32 +!CHECK: %[[VAL_46:.*]] = arith.select %[[VAL_43]], %[[VAL_39]], %[[VAL_38]] : i32 +!CHECK: %[[VAL_47:.*]] = arith.select %[[VAL_43]], %[[VAL_38]], %[[VAL_39]] : i32 +!CHECK: %[[VAL_48:.*]] = arith.subi %[[VAL_47]], %[[VAL_46]] overflow : i32 +!CHECK: %[[VAL_49:.*]] = arith.divui %[[VAL_48]], %[[VAL_45]] : i32 +!CHECK: %[[VAL_50:.*]] = arith.addi %[[VAL_49]], %[[VAL_42]] overflow : i32 +!CHECK: %[[VAL_51:.*]] = arith.cmpi slt, %[[VAL_47]], %[[VAL_46]] : i32 +!CHECK: %[[VAL_52:.*]] = arith.select %[[VAL_51]], %[[VAL_41]], %[[VAL_50]] : i32 +!CHECK: %[[VAL_53:.*]] = omp.new_cli +!CHECK: omp.canonical_loop(%[[VAL_53]]) %[[VAL_54:.*]] : i32 in range(%[[VAL_52]]) { +!CHECK: %[[VAL_55:.*]] = arith.muli %[[VAL_54]], %[[VAL_40]] : i32 +!CHECK: %[[VAL_56:.*]] = arith.addi %[[VAL_38]], %[[VAL_55]] : i32 +!CHECK: hlfir.assign %[[VAL_56]] to %[[VAL_37]]#0 : i32, !fir.ref +!CHECK: %[[VAL_57:.*]] = fir.load %[[VAL_14]]#0 : !fir.ref +!CHECK: %[[VAL_58:.*]] = fir.load %[[VAL_37]]#0 : !fir.ref +!CHECK: %[[VAL_59:.*]] = arith.addi %[[VAL_57]], %[[VAL_58]] : i32 +!CHECK: hlfir.assign %[[VAL_59]] to %[[VAL_12]]#0 : i32, !fir.ref +!CHECK: omp.terminator +!CHECK: } +!CHECK: omp.unroll_heuristic(%[[VAL_53]]) +!CHECK: omp.terminator +!CHECK: } +!CHECK: omp.unroll_heuristic(%[[VAL_32]]) +!CHECK: return +!CHECK: } diff --git a/flang/test/Lower/OpenMP/wsloop-chunks.f90 b/flang/test/Lower/OpenMP/wsloop-chunks.f90 index 29c02a3b3c8d5..f3f11d8c4a6c2 100644 --- a/flang/test/Lower/OpenMP/wsloop-chunks.f90 +++ b/flang/test/Lower/OpenMP/wsloop-chunks.f90 @@ -7,7 +7,7 @@ program wsloop integer :: i integer :: chunk -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "wsloop"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "WSLOOP"} { ! CHECK: %[[CHUNK_REF:.*]] = fir.alloca i32 {bindc_name = "chunk", uniq_name = "_QFEchunk"} ! CHECK: %[[VAL_0:.*]]:2 = hlfir.declare %[[CHUNK_REF]] {uniq_name = "_QFEchunk"} : (!fir.ref) -> (!fir.ref, !fir.ref) diff --git a/flang/test/Lower/OpenMP/wsloop-collapse.f90 b/flang/test/Lower/OpenMP/wsloop-collapse.f90 index a4d5cbdc03d3e..7ec40ab4b2f43 100644 --- a/flang/test/Lower/OpenMP/wsloop-collapse.f90 +++ b/flang/test/Lower/OpenMP/wsloop-collapse.f90 @@ -2,7 +2,7 @@ ! RUN: bbc -fopenmp -emit-hlfir %s -o - | FileCheck %s -!CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "wsloop_collapse"} { +!CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "WSLOOP_COLLAPSE"} { program wsloop_collapse !CHECK: %[[VAL_6:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFEa"} !CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-allocatable-array-minmax.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-allocatable-array-minmax.f90 index 58b68e5ec4cfd..e2f75bc8e4481 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-allocatable-array-minmax.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-allocatable-array-minmax.f90 @@ -156,7 +156,7 @@ program reduce15 ! CHECK: omp.yield ! CHECK: } -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "reduce15"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "REDUCE15"} { ! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFEarr) : !fir.ref>>> ! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = {{.*}}, uniq_name = "_QFEarr"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) ! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-allocatable.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-allocatable.f90 index 0a536eb34e7af..663851cba46c6 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-allocatable.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-allocatable.f90 @@ -63,7 +63,7 @@ program reduce ! CHECK: omp.yield ! CHECK: } -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "REDUCE"} { ! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFEi) : !fir.ref ! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box> {bindc_name = "r", uniq_name = "_QFEr"} diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-array-lb.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-array-lb.f90 index 9f0dd16002baf..2233a74600948 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-array-lb.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-array-lb.f90 @@ -31,5 +31,5 @@ program reduce ! CHECK: omp.yield(%[[ARG0]] : !fir.ref>>) ! CHECK: } -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "REDUCE"} { ! CHECK: omp.wsloop {{.*}} reduction(byref @add_reduction_byref_box_2xi32 %{{.*}} -> %{{.*}} : !fir.ref>>) diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-array-lb2.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-array-lb2.f90 index 5ada623a0ed23..211bde19da8db 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-array-lb2.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-array-lb2.f90 @@ -40,5 +40,5 @@ subroutine sub(a, lb, ub) ! CHECK: omp.yield(%[[ARG0]] : !fir.ref>>) ! CHECK: } -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "REDUCE"} { ! CHECK: omp.wsloop {{.*}} reduction(byref @add_reduction_byref_box_Uxi32 %{{.*}} -> %{{.*}} : !fir.ref>>) diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-array.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-array.f90 index 21261da49710c..b7882bcbc0d13 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-array.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-array.f90 @@ -65,7 +65,7 @@ program reduce ! CHECK: omp.yield ! CHECK: } -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "REDUCE"} { ! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFEi) : !fir.ref ! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QFEr) : !fir.ref> diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-array2.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-array2.f90 index ab8dcf1f076c0..7d90335a13a87 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-array2.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-array2.f90 @@ -65,7 +65,7 @@ program reduce ! CHECK: omp.yield ! CHECK: } -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "REDUCE"} { ! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFEi) : !fir.ref ! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QFEr) : !fir.ref> diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-min2.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-min2.f90 index 1e26f5a24d41e..d776bd7cfdd03 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-min2.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-min2.f90 @@ -28,7 +28,7 @@ program reduce ! CHECK: omp.yield(%[[VAL_2]] : i32) ! CHECK: } -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "REDUCE"} { ! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFEi) : !fir.ref ! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QFEr) : !fir.ref diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-multiple-clauses.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-multiple-clauses.f90 index e0a3b469f40c1..5133db0347034 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-multiple-clauses.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-multiple-clauses.f90 @@ -93,7 +93,7 @@ program main ! CHECK: omp.yield(%[[VAL_2]] : f64) ! CHECK: } -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "main"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "MAIN"} { ! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFEarray) : !fir.ref> ! CHECK: %[[VAL_1:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_2:.*]] = arith.constant 3 : index diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-pointer.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-pointer.f90 index 40b4302f24cd4..27b726376fbeb 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-pointer.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-pointer.f90 @@ -64,7 +64,7 @@ program reduce_pointer ! CHECK: omp.yield ! CHECK: } -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "reduce_pointer"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "REDUCE_POINTER"} { ! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} ! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box> {bindc_name = "v", uniq_name = "_QFEv"} diff --git a/flang/test/Lower/PowerPC/ppc-vec-extract-elem-order.f90 b/flang/test/Lower/PowerPC/ppc-vec-extract-elem-order.f90 index 73669c25b339e..d7d14581b4b7f 100644 --- a/flang/test/Lower/PowerPC/ppc-vec-extract-elem-order.f90 +++ b/flang/test/Lower/PowerPC/ppc-vec-extract-elem-order.f90 @@ -1,4 +1,4 @@ -! RUN: %flang_fc1 -flang-experimental-hlfir -emit-llvm %s -fno-ppc-native-vector-element-order -triple ppc64le-unknown-linux -o - | FileCheck --check-prefixes="LLVMIR" %s +! RUN: %flang_fc1 -emit-llvm %s -fno-ppc-native-vector-element-order -triple ppc64le-unknown-linux -o - | FileCheck --check-prefixes="LLVMIR" %s ! REQUIRES: target=powerpc{{.*}} !CHECK-LABEL: vec_extract_testr4i8 @@ -27,6 +27,7 @@ subroutine vec_extract_testi8i1(arg1, arg2, r) ! LLVMIR: %[[arg2:.*]] = load i8, ptr %{{[0-9]}}, align 1 ! LLVMIR: %[[urem:.*]] = urem i8 %[[arg2]], 2 ! LLVMIR: %[[sub:.*]] = sub i8 1, %[[urem]] -! LLVMIR: %[[r:.*]] = extractelement <2 x i64> %[[arg1]], i8 %[[sub]] +! LLVMIR: %[[idx:.*]] = zext i8 %[[sub]] to i64 +! LLVMIR: %[[r:.*]] = extractelement <2 x i64> %[[arg1]], i64 %[[idx]] ! LLVMIR: store i64 %[[r]], ptr %{{[0-9]}}, align 8 end subroutine vec_extract_testi8i1 diff --git a/flang/test/Lower/PowerPC/ppc-vec-extract.f90 b/flang/test/Lower/PowerPC/ppc-vec-extract.f90 index 0f279347b6b75..32c0dcfd66013 100644 --- a/flang/test/Lower/PowerPC/ppc-vec-extract.f90 +++ b/flang/test/Lower/PowerPC/ppc-vec-extract.f90 @@ -1,5 +1,5 @@ -! RUN: %flang_fc1 -flang-experimental-hlfir -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefixes="LLVMIR","LLVMIR-LE" %s -! RUN: %flang_fc1 -flang-experimental-hlfir -triple powerpc64-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefixes="LLVMIR","LLVMIR-BE" %s +! RUN: %flang_fc1 -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefixes="LLVMIR","LLVMIR-LE" %s +! RUN: %flang_fc1 -triple powerpc64-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefixes="LLVMIR","LLVMIR-BE" %s ! REQUIRES: target=powerpc{{.*}} !------------- @@ -19,8 +19,9 @@ subroutine vec_extract_testf32(x, i1, i2, i4, i8) ! LLVMIR: %[[i1:.*]] = load i8, ptr %{{[0-9]}}, align 1 ! LLVMIR: %[[u:.*]] = urem i8 %[[i1]], 4 ! LLVMIR-BE: %[[s:.*]] = sub i8 3, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <4 x float> %[[x]], i8 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <4 x float> %[[x]], i8 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i8 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i8 %[[u]] to i64 +! LLVMIR: %[[r:.*]] = extractelement <4 x float> %[[x]], i64 %[[idx]] ! LLVMIR: store float %[[r]], ptr %{{[0-9]}}, align 4 r = vec_extract(x, i2) @@ -29,8 +30,9 @@ subroutine vec_extract_testf32(x, i1, i2, i4, i8) ! LLVMIR: %[[i2:.*]] = load i16, ptr %{{[0-9]}}, align 2 ! LLVMIR: %[[u:.*]] = urem i16 %[[i2]], 4 ! LLVMIR-BE: %[[s:.*]] = sub i16 3, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <4 x float> %[[x]], i16 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <4 x float> %[[x]], i16 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i16 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i16 %[[u]] to i64 +! LLVMIR: %[[r:.*]] = extractelement <4 x float> %[[x]], i64 %[[idx]] ! LLVMIR: store float %[[r]], ptr %{{[0-9]}}, align 4 r = vec_extract(x, i4) @@ -39,18 +41,19 @@ subroutine vec_extract_testf32(x, i1, i2, i4, i8) ! LLVMIR: %[[i4:.*]] = load i32, ptr %{{[0-9]}}, align 4 ! LLVMIR: %[[u:.*]] = urem i32 %[[i4]], 4 ! LLVMIR-BE: %[[s:.*]] = sub i32 3, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <4 x float> %[[x]], i32 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <4 x float> %[[x]], i32 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i32 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i32 %[[u]] to i64 +! LLVMIR: %[[r:.*]] = extractelement <4 x float> %[[x]], i64 %[[idx]] ! LLVMIR: store float %[[r]], ptr %{{[0-9]}}, align 4 r = vec_extract(x, i8) ! LLVMIR: %[[x:.*]] = load <4 x float>, ptr %{{[0-9]}}, align 16 ! LLVMIR: %[[i8:.*]] = load i64, ptr %{{[0-9]}}, align 8 -! LLVMIR: %[[u:.*]] = urem i64 %[[i8]], 4 -! LLVMIR-BE: %[[s:.*]] = sub i64 3, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <4 x float> %[[x]], i64 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <4 x float> %[[x]], i64 %[[s]] +! LLVMIR-BE: %[[u:.*]] = urem i64 %[[i8]], 4 +! LLVMIR-BE: %[[idx:.*]] = sub i64 3, %[[u]] +! LLVMIR-LE: %[[idx:.*]] = urem i64 %[[i8]], 4 +! LLVMIR: %[[r:.*]] = extractelement <4 x float> %[[x]], i64 %[[idx]] ! LLVMIR: store float %[[r]], ptr %{{[0-9]}}, align 4 end subroutine vec_extract_testf32 @@ -68,8 +71,9 @@ subroutine vec_extract_testf64(x, i1, i2, i4, i8) ! LLVMIR: %[[i1:.*]] = load i8, ptr %{{[0-9]}}, align 1 ! LLVMIR: %[[u:.*]] = urem i8 %[[i1]], 2 ! LLVMIR-BE: %[[s:.*]] = sub i8 1, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <2 x double> %[[x]], i8 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <2 x double> %[[x]], i8 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i8 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i8 %[[u]] to i64 +! LLVMIR: %[[r:.*]] = extractelement <2 x double> %[[x]], i64 %[[idx]] ! LLVMIR: store double %[[r]], ptr %{{[0-9]}}, align 8 r = vec_extract(x, i2) @@ -78,8 +82,9 @@ subroutine vec_extract_testf64(x, i1, i2, i4, i8) ! LLVMIR: %[[i2:.*]] = load i16, ptr %{{[0-9]}}, align 2 ! LLVMIR: %[[u:.*]] = urem i16 %[[i2]], 2 ! LLVMIR-BE: %[[s:.*]] = sub i16 1, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <2 x double> %[[x]], i16 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <2 x double> %[[x]], i16 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i16 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i16 %[[u]] to i64 +! LLVMIR: %[[r:.*]] = extractelement <2 x double> %[[x]], i64 %[[idx]] ! LLVMIR: store double %[[r]], ptr %{{[0-9]}}, align 8 @@ -89,18 +94,19 @@ subroutine vec_extract_testf64(x, i1, i2, i4, i8) ! LLVMIR: %[[i4:.*]] = load i32, ptr %{{[0-9]}}, align 4 ! LLVMIR: %[[u:.*]] = urem i32 %[[i4]], 2 ! LLVMIR-BE: %[[s:.*]] = sub i32 1, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <2 x double> %[[x]], i32 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <2 x double> %[[x]], i32 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i32 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i32 %[[u]] to i64 +! LLVMIR: %[[r:.*]] = extractelement <2 x double> %[[x]], i64 %[[idx]] ! LLVMIR: store double %[[r]], ptr %{{[0-9]}}, align 8 r = vec_extract(x, i8) ! LLVMIR: %[[x:.*]] = load <2 x double>, ptr %{{[0-9]}}, align 16 ! LLVMIR: %[[i8:.*]] = load i64, ptr %{{[0-9]}}, align 8 -! LLVMIR: %[[u:.*]] = urem i64 %[[i8]], 2 -! LLVMIR-BE: %[[s:.*]] = sub i64 1, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <2 x double> %[[x]], i64 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <2 x double> %[[x]], i64 %[[s]] +! LLVMIR-BE: %[[u:.*]] = urem i64 %[[i8]], 2 +! LLVMIR-BE: %[[idx:.*]] = sub i64 1, %[[u]] +! LLVMIR-LE: %[[idx:.*]] = urem i64 %[[i8]], 2 +! LLVMIR: %[[r:.*]] = extractelement <2 x double> %[[x]], i64 %[[idx]] ! LLVMIR: store double %[[r]], ptr %{{[0-9]}}, align 8 end subroutine vec_extract_testf64 @@ -118,8 +124,9 @@ subroutine vec_extract_testi8(x, i1, i2, i4, i8) ! LLVMIR: %[[i1:.*]] = load i8, ptr %{{[0-9]}}, align 1 ! LLVMIR: %[[u:.*]] = urem i8 %[[i1]], 16 ! LLVMIR-BE: %[[s:.*]] = sub i8 15, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <16 x i8> %[[x]], i8 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <16 x i8> %[[x]], i8 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i8 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i8 %[[u]] to i64 +! LLVMIR: %[[r:.*]] = extractelement <16 x i8> %[[x]], i64 %[[idx]] ! LLVMIR: store i8 %[[r]], ptr %{{[0-9]}}, align 1 r = vec_extract(x, i2) @@ -128,8 +135,9 @@ subroutine vec_extract_testi8(x, i1, i2, i4, i8) ! LLVMIR: %[[i2:.*]] = load i16, ptr %{{[0-9]}}, align 2 ! LLVMIR: %[[u:.*]] = urem i16 %[[i2]], 16 ! LLVMIR-BE: %[[s:.*]] = sub i16 15, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <16 x i8> %[[x]], i16 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <16 x i8> %[[x]], i16 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i16 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i16 %[[u]] to i64 +! LLVMIR: %[[r:.*]] = extractelement <16 x i8> %[[x]], i64 %[[idx]] ! LLVMIR: store i8 %[[r]], ptr %{{[0-9]}}, align 1 r = vec_extract(x, i4) @@ -138,18 +146,19 @@ subroutine vec_extract_testi8(x, i1, i2, i4, i8) ! LLVMIR: %[[i4:.*]] = load i32, ptr %{{[0-9]}}, align 4 ! LLVMIR: %[[u:.*]] = urem i32 %[[i4]], 16 ! LLVMIR-BE: %[[s:.*]] = sub i32 15, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <16 x i8> %[[x]], i32 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <16 x i8> %[[x]], i32 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i32 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i32 %[[u]] to i64 +! LLVMIR: %[[r:.*]] = extractelement <16 x i8> %[[x]], i64 %[[idx]] ! LLVMIR: store i8 %[[r]], ptr %{{[0-9]}}, align 1 r = vec_extract(x, i8) ! LLVMIR: %[[x:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 ! LLVMIR: %[[i8:.*]] = load i64, ptr %{{[0-9]}}, align 8 -! LLVMIR: %[[u:.*]] = urem i64 %[[i8]], 16 -! LLVMIR-BE: %[[s:.*]] = sub i64 15, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <16 x i8> %[[x]], i64 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <16 x i8> %[[x]], i64 %[[s]] +! LLVMIR-BE: %[[u:.*]] = urem i64 %[[i8]], 16 +! LLVMIR-BE: %[[idx:.*]] = sub i64 15, %[[u]] +! LLVMIR-LE: %[[idx:.*]] = urem i64 %[[i8]], 16 +! LLVMIR: %[[r:.*]] = extractelement <16 x i8> %[[x]], i64 %[[idx]] ! LLVMIR: store i8 %[[r]], ptr %{{[0-9]}}, align 1 end subroutine vec_extract_testi8 @@ -167,8 +176,9 @@ subroutine vec_extract_testi16(x, i1, i2, i4, i8) ! LLVMIR: %[[i1:.*]] = load i8, ptr %{{[0-9]}}, align 1 ! LLVMIR: %[[u:.*]] = urem i8 %[[i1]], 8 ! LLVMIR-BE: %[[s:.*]] = sub i8 7, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <8 x i16> %[[x]], i8 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <8 x i16> %[[x]], i8 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i8 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i8 %[[u]] to i64 +! LLVMIR: %[[r:.*]] = extractelement <8 x i16> %[[x]], i64 %[[idx]] ! LLVMIR: store i16 %[[r]], ptr %{{[0-9]}}, align 2 r = vec_extract(x, i2) @@ -177,8 +187,9 @@ subroutine vec_extract_testi16(x, i1, i2, i4, i8) ! LLVMIR: %[[i2:.*]] = load i16, ptr %{{[0-9]}}, align 2 ! LLVMIR: %[[u:.*]] = urem i16 %[[i2]], 8 ! LLVMIR-BE: %[[s:.*]] = sub i16 7, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <8 x i16> %[[x]], i16 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <8 x i16> %[[x]], i16 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i16 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i16 %[[u]] to i64 +! LLVMIR: %[[r:.*]] = extractelement <8 x i16> %[[x]], i64 %[[idx]] ! LLVMIR: store i16 %[[r]], ptr %{{[0-9]}}, align 2 r = vec_extract(x, i4) @@ -187,18 +198,19 @@ subroutine vec_extract_testi16(x, i1, i2, i4, i8) ! LLVMIR: %[[i4:.*]] = load i32, ptr %{{[0-9]}}, align 4 ! LLVMIR: %[[u:.*]] = urem i32 %[[i4]], 8 ! LLVMIR-BE: %[[s:.*]] = sub i32 7, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <8 x i16> %[[x]], i32 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <8 x i16> %[[x]], i32 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i32 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i32 %[[u]] to i64 +! LLVMIR: %[[r:.*]] = extractelement <8 x i16> %[[x]], i64 %[[idx]] ! LLVMIR: store i16 %[[r]], ptr %{{[0-9]}}, align 2 r = vec_extract(x, i8) ! LLVMIR: %[[x:.*]] = load <8 x i16>, ptr %{{[0-9]}}, align 16 ! LLVMIR: %[[i8:.*]] = load i64, ptr %{{[0-9]}}, align 8 -! LLVMIR: %[[u:.*]] = urem i64 %[[i8]], 8 -! LLVMIR-BE: %[[s:.*]] = sub i64 7, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <8 x i16> %[[x]], i64 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <8 x i16> %[[x]], i64 %[[s]] +! LLVMIR-BE: %[[u:.*]] = urem i64 %[[i8]], 8 +! LLVMIR-BE: %[[idx:.*]] = sub i64 7, %[[u]] +! LLVMIR-LE: %[[idx:.*]] = urem i64 %[[i8]], 8 +! LLVMIR: %[[r:.*]] = extractelement <8 x i16> %[[x]], i64 %[[idx]] ! LLVMIR: store i16 %[[r]], ptr %{{[0-9]}}, align 2 end subroutine vec_extract_testi16 @@ -216,8 +228,9 @@ subroutine vec_extract_testi32(x, i1, i2, i4, i8) ! LLVMIR: %[[i1:.*]] = load i8, ptr %{{[0-9]}}, align 1 ! LLVMIR: %[[u:.*]] = urem i8 %[[i1]], 4 ! LLVMIR-BE: %[[s:.*]] = sub i8 3, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <4 x i32> %[[x]], i8 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <4 x i32> %[[x]], i8 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i8 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i8 %[[u]] to i64 +! LLVMIR: %[[r:.*]] = extractelement <4 x i32> %[[x]], i64 %[[idx]] ! LLVMIR: store i32 %[[r]], ptr %{{[0-9]}}, align 4 r = vec_extract(x, i2) @@ -226,8 +239,9 @@ subroutine vec_extract_testi32(x, i1, i2, i4, i8) ! LLVMIR: %[[i2:.*]] = load i16, ptr %{{[0-9]}}, align 2 ! LLVMIR: %[[u:.*]] = urem i16 %[[i2]], 4 ! LLVMIR-BE: %[[s:.*]] = sub i16 3, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <4 x i32> %[[x]], i16 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <4 x i32> %[[x]], i16 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i16 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i16 %[[u]] to i64 +! LLVMIR: %[[r:.*]] = extractelement <4 x i32> %[[x]], i64 %[[idx]] ! LLVMIR: store i32 %[[r]], ptr %{{[0-9]}}, align 4 r = vec_extract(x, i4) @@ -236,18 +250,19 @@ subroutine vec_extract_testi32(x, i1, i2, i4, i8) ! LLVMIR: %[[i4:.*]] = load i32, ptr %{{[0-9]}}, align 4 ! LLVMIR: %[[u:.*]] = urem i32 %[[i4]], 4 ! LLVMIR-BE: %[[s:.*]] = sub i32 3, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <4 x i32> %[[x]], i32 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <4 x i32> %[[x]], i32 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i32 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i32 %[[u]] to i64 +! LLVMIR: %[[r:.*]] = extractelement <4 x i32> %[[x]], i64 %[[idx]] ! LLVMIR: store i32 %[[r]], ptr %{{[0-9]}}, align 4 r = vec_extract(x, i8) ! LLVMIR: %[[x:.*]] = load <4 x i32>, ptr %{{[0-9]}}, align 16 ! LLVMIR: %[[i8:.*]] = load i64, ptr %{{[0-9]}}, align 8 -! LLVMIR: %[[u:.*]] = urem i64 %[[i8]], 4 -! LLVMIR-BE: %[[s:.*]] = sub i64 3, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <4 x i32> %[[x]], i64 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <4 x i32> %[[x]], i64 %[[s]] +! LLVMIR-BE: %[[u:.*]] = urem i64 %[[i8]], 4 +! LLVMIR-BE: %[[idx:.*]] = sub i64 3, %[[u]] +! LLVMIR-LE: %[[idx:.*]] = urem i64 %[[i8]], 4 +! LLVMIR: %[[r:.*]] = extractelement <4 x i32> %[[x]], i64 %[[idx]] ! LLVMIR: store i32 %[[r]], ptr %{{[0-9]}}, align 4 end subroutine vec_extract_testi32 @@ -265,8 +280,9 @@ subroutine vec_extract_testi64(x, i1, i2, i4, i8) ! LLVMIR: %[[i1:.*]] = load i8, ptr %{{[0-9]}}, align 1 ! LLVMIR: %[[u:.*]] = urem i8 %[[i1]], 2 ! LLVMIR-BE: %[[s:.*]] = sub i8 1, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <2 x i64> %[[x]], i8 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <2 x i64> %[[x]], i8 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i8 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i8 %[[u]] to i64 +! LLVMIR: %[[r:.*]] = extractelement <2 x i64> %[[x]], i64 %[[idx]] ! LLVMIR: store i64 %[[r]], ptr %{{[0-9]}}, align 8 r = vec_extract(x, i2) @@ -275,8 +291,9 @@ subroutine vec_extract_testi64(x, i1, i2, i4, i8) ! LLVMIR: %[[i2:.*]] = load i16, ptr %{{[0-9]}}, align 2 ! LLVMIR: %[[u:.*]] = urem i16 %[[i2]], 2 ! LLVMIR-BE: %[[s:.*]] = sub i16 1, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <2 x i64> %[[x]], i16 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <2 x i64> %[[x]], i16 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i16 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i16 %[[u]] to i64 +! LLVMIR: %[[r:.*]] = extractelement <2 x i64> %[[x]], i64 %[[idx]] ! LLVMIR: store i64 %[[r]], ptr %{{[0-9]}}, align 8 r = vec_extract(x, i4) @@ -285,17 +302,18 @@ subroutine vec_extract_testi64(x, i1, i2, i4, i8) ! LLVMIR: %[[i4:.*]] = load i32, ptr %{{[0-9]}}, align 4 ! LLVMIR: %[[u:.*]] = urem i32 %[[i4]], 2 ! LLVMIR-BE: %[[s:.*]] = sub i32 1, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <2 x i64> %[[x]], i32 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <2 x i64> %[[x]], i32 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i32 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i32 %[[u]] to i64 +! LLVMIR: %[[r:.*]] = extractelement <2 x i64> %[[x]], i64 %[[idx]] ! LLVMIR: store i64 %[[r]], ptr %{{[0-9]}}, align 8 r = vec_extract(x, i8) ! LLVMIR: %[[x:.*]] = load <2 x i64>, ptr %{{[0-9]}}, align 16 ! LLVMIR: %[[i8:.*]] = load i64, ptr %{{[0-9]}}, align 8 -! LLVMIR: %[[u:.*]] = urem i64 %[[i8]], 2 -! LLVMIR-BE: %[[s:.*]] = sub i64 1, %[[u]] -! LLVMIR-LE: %[[r:.*]] = extractelement <2 x i64> %[[x]], i64 %[[u]] -! LLVMIR-BE: %[[r:.*]] = extractelement <2 x i64> %[[x]], i64 %[[s]] +! LLVMIR-BE: %[[u:.*]] = urem i64 %[[i8]], 2 +! LLVMIR-BE: %[[idx:.*]] = sub i64 1, %[[u]] +! LLVMIR-LE: %[[idx:.*]] = urem i64 %[[i8]], 2 +! LLVMIR: %[[r:.*]] = extractelement <2 x i64> %[[x]], i64 %[[idx]] ! LLVMIR: store i64 %[[r]], ptr %{{[0-9]}}, align 8 end subroutine vec_extract_testi64 diff --git a/flang/test/Lower/PowerPC/ppc-vec-insert-elem-order.f90 b/flang/test/Lower/PowerPC/ppc-vec-insert-elem-order.f90 index f64df46f170ab..b30065d74e46b 100644 --- a/flang/test/Lower/PowerPC/ppc-vec-insert-elem-order.f90 +++ b/flang/test/Lower/PowerPC/ppc-vec-insert-elem-order.f90 @@ -1,4 +1,4 @@ -! RUN: %flang_fc1 -flang-experimental-hlfir -emit-llvm %s -fno-ppc-native-vector-element-order -triple ppc64le-unknown-linux -o - | FileCheck --check-prefixes="LLVMIR" %s +! RUN: %flang_fc1 -emit-llvm %s -fno-ppc-native-vector-element-order -triple ppc64le-unknown-linux -o - | FileCheck --check-prefixes="LLVMIR" %s ! REQUIRES: target=powerpc{{.*}} !CHECK-LABEL: vec_insert_testf32i64 @@ -31,6 +31,7 @@ subroutine vec_insert_testi64i8(v, x, i1, i2, i4, i8) ! LLVMIR: %[[i1:.*]] = load i8, ptr %{{[0-9]}}, align 1 ! LLVMIR: %[[urem:.*]] = urem i8 %[[i1]], 2 ! LLVMIR: %[[sub:.*]] = sub i8 1, %[[urem]] -! LLVMIR: %[[r:.*]] = insertelement <2 x i64> %[[x]], i64 %[[v]], i8 %[[sub]] +! LLVMIR: %[[idx:.*]] = zext i8 %[[sub]] to i64 +! LLVMIR: %[[r:.*]] = insertelement <2 x i64> %[[x]], i64 %[[v]], i64 %[[idx]] ! LLVMIR: store <2 x i64> %[[r]], ptr %{{[0-9]}}, align 16 end subroutine vec_insert_testi64i8 diff --git a/flang/test/Lower/PowerPC/ppc-vec-insert.f90 b/flang/test/Lower/PowerPC/ppc-vec-insert.f90 index dd57fcc67be08..26bc7fc114cec 100644 --- a/flang/test/Lower/PowerPC/ppc-vec-insert.f90 +++ b/flang/test/Lower/PowerPC/ppc-vec-insert.f90 @@ -1,5 +1,5 @@ -! RUN: %flang_fc1 -flang-experimental-hlfir -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefixes="LLVMIR","LLVMIR-LE" %s -! RUN: %flang_fc1 -flang-experimental-hlfir -triple powerpc64-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefixes="LLVMIR","LLVMIR-BE" %s +! RUN: %flang_fc1 -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefixes="LLVMIR","LLVMIR-LE" %s +! RUN: %flang_fc1 -triple powerpc64-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefixes="LLVMIR","LLVMIR-BE" %s ! REQUIRES: target=powerpc{{.*}} ! vec_insert @@ -20,8 +20,9 @@ subroutine vec_insert_testf32(v, x, i1, i2, i4, i8) ! LLVMIR: %[[i1:.*]] = load i8, ptr %{{[0-9]}}, align 1 ! LLVMIR: %[[urem:.*]] = urem i8 %[[i1]], 4 ! LLVMIR-BE: %[[s:.*]] = sub i8 3, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <4 x float> %[[x]], float %[[v]], i8 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <4 x float> %[[x]], float %[[v]], i8 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i8 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i8 %[[urem]] to i64 +! LLVMIR: %[[r:.*]] = insertelement <4 x float> %[[x]], float %[[v]], i64 %[[idx]] ! LLVMIR: store <4 x float> %[[r]], ptr %{{[0-9]}}, align 16 r = vec_insert(v, x, i2) @@ -31,8 +32,9 @@ subroutine vec_insert_testf32(v, x, i1, i2, i4, i8) ! LLVMIR: %[[i2:.*]] = load i16, ptr %{{[0-9]}}, align 2 ! LLVMIR: %[[urem:.*]] = urem i16 %[[i2]], 4 ! LLVMIR-BE: %[[s:.*]] = sub i16 3, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <4 x float> %[[x]], float %[[v]], i16 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <4 x float> %[[x]], float %[[v]], i16 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i16 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i16 %[[urem]] to i64 +! LLVMIR: %[[r:.*]] = insertelement <4 x float> %[[x]], float %[[v]], i64 %[[idx]] ! LLVMIR: store <4 x float> %[[r]], ptr %{{[0-9]}}, align 16 r = vec_insert(v, x, i4) @@ -42,8 +44,9 @@ subroutine vec_insert_testf32(v, x, i1, i2, i4, i8) ! LLVMIR: %[[i4:.*]] = load i32, ptr %{{[0-9]}}, align 4 ! LLVMIR: %[[urem:.*]] = urem i32 %[[i4]], 4 ! LLVMIR-BE: %[[s:.*]] = sub i32 3, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <4 x float> %[[x]], float %[[v]], i32 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <4 x float> %[[x]], float %[[v]], i32 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i32 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i32 %[[urem]] to i64 +! LLVMIR: %[[r:.*]] = insertelement <4 x float> %[[x]], float %[[v]], i64 %[[idx]] ! LLVMIR: store <4 x float> %[[r]], ptr %{{[0-9]}}, align 16 r = vec_insert(v, x, i8) @@ -51,10 +54,10 @@ subroutine vec_insert_testf32(v, x, i1, i2, i4, i8) ! LLVMIR: %[[v:.*]] = load float, ptr %{{[0-9]}}, align 4 ! LLVMIR: %[[x:.*]] = load <4 x float>, ptr %{{[0-9]}}, align 16 ! LLVMIR: %[[i8:.*]] = load i64, ptr %{{[0-9]}}, align 8 -! LLVMIR: %[[urem:.*]] = urem i64 %[[i8]], 4 -! LLVMIR-BE: %[[s:.*]] = sub i64 3, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <4 x float> %[[x]], float %[[v]], i64 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <4 x float> %[[x]], float %[[v]], i64 %[[s]] +! LLVMIR-BE: %[[urem:.*]] = urem i64 %[[i8]], 4 +! LLVMIR-BE: %[[idx:.*]] = sub i64 3, %[[urem]] +! LLVMIR-LE: %[[idx:.*]] = urem i64 %[[i8]], 4 +! LLVMIR: %[[r:.*]] = insertelement <4 x float> %[[x]], float %[[v]], i64 %[[idx]] ! LLVMIR: store <4 x float> %[[r]], ptr %{{[0-9]}}, align 16 end subroutine vec_insert_testf32 @@ -74,8 +77,9 @@ subroutine vec_insert_testf64(v, x, i1, i2, i4, i8) ! LLVMIR: %[[i1:.*]] = load i8, ptr %{{[0-9]}}, align 1 ! LLVMIR: %[[urem:.*]] = urem i8 %[[i1]], 2 ! LLVMIR-BE: %[[s:.*]] = sub i8 1, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <2 x double> %[[x]], double %[[v]], i8 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <2 x double> %[[x]], double %[[v]], i8 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i8 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i8 %[[urem]] to i64 +! LLVMIR: %[[r:.*]] = insertelement <2 x double> %[[x]], double %[[v]], i64 %[[idx]] ! LLVMIR: store <2 x double> %[[r]], ptr %{{[0-9]}}, align 16 r = vec_insert(v, x, i2) @@ -85,8 +89,9 @@ subroutine vec_insert_testf64(v, x, i1, i2, i4, i8) ! LLVMIR: %[[i2:.*]] = load i16, ptr %{{[0-9]}}, align 2 ! LLVMIR: %[[urem:.*]] = urem i16 %[[i2]], 2 ! LLVMIR-BE: %[[s:.*]] = sub i16 1, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <2 x double> %[[x]], double %[[v]], i16 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <2 x double> %[[x]], double %[[v]], i16 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i16 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i16 %[[urem]] to i64 +! LLVMIR: %[[r:.*]] = insertelement <2 x double> %[[x]], double %[[v]], i64 %[[idx]] ! LLVMIR: store <2 x double> %[[r]], ptr %{{[0-9]}}, align 16 r = vec_insert(v, x, i4) @@ -96,8 +101,9 @@ subroutine vec_insert_testf64(v, x, i1, i2, i4, i8) ! LLVMIR: %[[i4:.*]] = load i32, ptr %{{[0-9]}}, align 4 ! LLVMIR: %[[urem:.*]] = urem i32 %[[i4]], 2 ! LLVMIR-BE: %[[s:.*]] = sub i32 1, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <2 x double> %[[x]], double %[[v]], i32 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <2 x double> %[[x]], double %[[v]], i32 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i32 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i32 %[[urem]] to i64 +! LLVMIR: %[[r:.*]] = insertelement <2 x double> %[[x]], double %[[v]], i64 %[[idx]] ! LLVMIR: store <2 x double> %[[r]], ptr %{{[0-9]}}, align 16 r = vec_insert(v, x, i8) @@ -105,10 +111,10 @@ subroutine vec_insert_testf64(v, x, i1, i2, i4, i8) ! LLVMIR: %[[v:.*]] = load double, ptr %{{[0-9]}}, align 8 ! LLVMIR: %[[x:.*]] = load <2 x double>, ptr %{{[0-9]}}, align 16 ! LLVMIR: %[[i8:.*]] = load i64, ptr %{{[0-9]}}, align 8 -! LLVMIR: %[[urem:.*]] = urem i64 %[[i8]], 2 -! LLVMIR-BE: %[[s:.*]] = sub i64 1, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <2 x double> %[[x]], double %[[v]], i64 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <2 x double> %[[x]], double %[[v]], i64 %[[s]] +! LLVMIR-BE: %[[urem:.*]] = urem i64 %[[i8]], 2 +! LLVMIR-BE: %[[idx:.*]] = sub i64 1, %[[urem]] +! LLVMIR-LE: %[[idx:.*]] = urem i64 %[[i8]], 2 +! LLVMIR: %[[r:.*]] = insertelement <2 x double> %[[x]], double %[[v]], i64 %[[idx]] ! LLVMIR: store <2 x double> %[[r]], ptr %{{[0-9]}}, align 16 end subroutine vec_insert_testf64 @@ -128,8 +134,9 @@ subroutine vec_insert_testi8(v, x, i1, i2, i4, i8) ! LLVMIR: %[[i1:.*]] = load i8, ptr %{{[0-9]}}, align 1 ! LLVMIR: %[[urem:.*]] = urem i8 %[[i1]], 16 ! LLVMIR-BE: %[[s:.*]] = sub i8 15, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <16 x i8> %[[x]], i8 %[[v]], i8 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <16 x i8> %[[x]], i8 %[[v]], i8 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i8 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i8 %[[urem]] to i64 +! LLVMIR: %[[r:.*]] = insertelement <16 x i8> %[[x]], i8 %[[v]], i64 %[[idx]] ! LLVMIR: store <16 x i8> %[[r]], ptr %{{[0-9]}}, align 16 r = vec_insert(v, x, i2) @@ -139,8 +146,9 @@ subroutine vec_insert_testi8(v, x, i1, i2, i4, i8) ! LLVMIR: %[[i2:.*]] = load i16, ptr %{{[0-9]}}, align 2 ! LLVMIR: %[[urem:.*]] = urem i16 %[[i2]], 16 ! LLVMIR-BE: %[[s:.*]] = sub i16 15, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <16 x i8> %[[x]], i8 %[[v]], i16 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <16 x i8> %[[x]], i8 %[[v]], i16 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i16 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i16 %[[urem]] to i64 +! LLVMIR: %[[r:.*]] = insertelement <16 x i8> %[[x]], i8 %[[v]], i64 %[[idx]] ! LLVMIR: store <16 x i8> %[[r]], ptr %{{[0-9]}}, align 16 r = vec_insert(v, x, i4) @@ -150,8 +158,9 @@ subroutine vec_insert_testi8(v, x, i1, i2, i4, i8) ! LLVMIR: %[[i4:.*]] = load i32, ptr %{{[0-9]}}, align 4 ! LLVMIR: %[[urem:.*]] = urem i32 %[[i4]], 16 ! LLVMIR-BE: %[[s:.*]] = sub i32 15, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <16 x i8> %[[x]], i8 %[[v]], i32 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <16 x i8> %[[x]], i8 %[[v]], i32 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i32 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i32 %[[urem]] to i64 +! LLVMIR: %[[r:.*]] = insertelement <16 x i8> %[[x]], i8 %[[v]], i64 %[[idx]] ! LLVMIR: store <16 x i8> %[[r]], ptr %{{[0-9]}}, align 16 r = vec_insert(v, x, i8) @@ -159,10 +168,10 @@ subroutine vec_insert_testi8(v, x, i1, i2, i4, i8) ! LLVMIR: %[[v:.*]] = load i8, ptr %{{[0-9]}}, align 1 ! LLVMIR: %[[x:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 ! LLVMIR: %[[i8:.*]] = load i64, ptr %{{[0-9]}}, align 8 -! LLVMIR: %[[urem:.*]] = urem i64 %[[i8]], 16 -! LLVMIR-BE: %[[s:.*]] = sub i64 15, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <16 x i8> %[[x]], i8 %[[v]], i64 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <16 x i8> %[[x]], i8 %[[v]], i64 %[[s]] +! LLVMIR-BE: %[[urem:.*]] = urem i64 %[[i8]], 16 +! LLVMIR-BE: %[[idx:.*]] = sub i64 15, %[[urem]] +! LLVMIR-LE: %[[idx:.*]] = urem i64 %[[i8]], 16 +! LLVMIR: %[[r:.*]] = insertelement <16 x i8> %[[x]], i8 %[[v]], i64 %[[idx]] ! LLVMIR: store <16 x i8> %[[r]], ptr %{{[0-9]}}, align 16 end subroutine vec_insert_testi8 @@ -182,8 +191,9 @@ subroutine vec_insert_testi16(v, x, i1, i2, i4, i8) ! LLVMIR: %[[i1:.*]] = load i8, ptr %{{[0-9]}}, align 1 ! LLVMIR: %[[urem:.*]] = urem i8 %[[i1]], 8 ! LLVMIR-BE: %[[s:.*]] = sub i8 7, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <8 x i16> %[[x]], i16 %[[v]], i8 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <8 x i16> %[[x]], i16 %[[v]], i8 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i8 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i8 %[[urem]] to i64 +! LLVMIR: %[[r:.*]] = insertelement <8 x i16> %[[x]], i16 %[[v]], i64 %[[idx]] ! LLVMIR: store <8 x i16> %[[r]], ptr %{{[0-9]}}, align 16 r = vec_insert(v, x, i2) @@ -193,8 +203,9 @@ subroutine vec_insert_testi16(v, x, i1, i2, i4, i8) ! LLVMIR: %[[i2:.*]] = load i16, ptr %{{[0-9]}}, align 2 ! LLVMIR: %[[urem:.*]] = urem i16 %[[i2]], 8 ! LLVMIR-BE: %[[s:.*]] = sub i16 7, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <8 x i16> %[[x]], i16 %[[v]], i16 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <8 x i16> %[[x]], i16 %[[v]], i16 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i16 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i16 %[[urem]] to i64 +! LLVMIR: %[[r:.*]] = insertelement <8 x i16> %[[x]], i16 %[[v]], i64 %[[idx]] ! LLVMIR: store <8 x i16> %[[r]], ptr %{{[0-9]}}, align 16 r = vec_insert(v, x, i4) @@ -204,8 +215,9 @@ subroutine vec_insert_testi16(v, x, i1, i2, i4, i8) ! LLVMIR: %[[i4:.*]] = load i32, ptr %{{[0-9]}}, align 4 ! LLVMIR: %[[urem:.*]] = urem i32 %[[i4]], 8 ! LLVMIR-BE: %[[s:.*]] = sub i32 7, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <8 x i16> %[[x]], i16 %[[v]], i32 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <8 x i16> %[[x]], i16 %[[v]], i32 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i32 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i32 %[[urem]] to i64 +! LLVMIR: %[[r:.*]] = insertelement <8 x i16> %[[x]], i16 %[[v]], i64 %[[idx]] ! LLVMIR: store <8 x i16> %[[r]], ptr %{{[0-9]}}, align 16 r = vec_insert(v, x, i8) @@ -213,10 +225,10 @@ subroutine vec_insert_testi16(v, x, i1, i2, i4, i8) ! LLVMIR: %[[v:.*]] = load i16, ptr %{{[0-9]}}, align 2 ! LLVMIR: %[[x:.*]] = load <8 x i16>, ptr %{{[0-9]}}, align 16 ! LLVMIR: %[[i8:.*]] = load i64, ptr %{{[0-9]}}, align 8 -! LLVMIR: %[[urem:.*]] = urem i64 %[[i8]], 8 -! LLVMIR-BE: %[[s:.*]] = sub i64 7, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <8 x i16> %[[x]], i16 %[[v]], i64 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <8 x i16> %[[x]], i16 %[[v]], i64 %[[s]] +! LLVMIR-BE: %[[urem:.*]] = urem i64 %[[i8]], 8 +! LLVMIR-BE: %[[idx:.*]] = sub i64 7, %[[urem]] +! LLVMIR-LE: %[[idx:.*]] = urem i64 %[[i8]], 8 +! LLVMIR: %[[r:.*]] = insertelement <8 x i16> %[[x]], i16 %[[v]], i64 %[[idx]] ! LLVMIR: store <8 x i16> %[[r]], ptr %{{[0-9]}}, align 16 end subroutine vec_insert_testi16 @@ -236,8 +248,9 @@ subroutine vec_insert_testi32(v, x, i1, i2, i4, i8) ! LLVMIR: %[[i1:.*]] = load i8, ptr %{{[0-9]}}, align 1 ! LLVMIR: %[[urem:.*]] = urem i8 %[[i1]], 4 ! LLVMIR-BE: %[[s:.*]] = sub i8 3, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <4 x i32> %[[x]], i32 %[[v]], i8 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <4 x i32> %[[x]], i32 %[[v]], i8 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i8 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i8 %[[urem]] to i64 +! LLVMIR: %[[r:.*]] = insertelement <4 x i32> %[[x]], i32 %[[v]], i64 %[[idx]] ! LLVMIR: store <4 x i32> %[[r]], ptr %{{[0-9]}}, align 16 r = vec_insert(v, x, i2) @@ -247,8 +260,9 @@ subroutine vec_insert_testi32(v, x, i1, i2, i4, i8) ! LLVMIR: %[[i2:.*]] = load i16, ptr %{{[0-9]}}, align 2 ! LLVMIR: %[[urem:.*]] = urem i16 %[[i2]], 4 ! LLVMIR-BE: %[[s:.*]] = sub i16 3, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <4 x i32> %[[x]], i32 %[[v]], i16 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <4 x i32> %[[x]], i32 %[[v]], i16 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i16 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i16 %[[urem]] to i64 +! LLVMIR: %[[r:.*]] = insertelement <4 x i32> %[[x]], i32 %[[v]], i64 %[[idx]] ! LLVMIR: store <4 x i32> %[[r]], ptr %{{[0-9]}}, align 16 r = vec_insert(v, x, i4) @@ -258,8 +272,9 @@ subroutine vec_insert_testi32(v, x, i1, i2, i4, i8) ! LLVMIR: %[[i4:.*]] = load i32, ptr %{{[0-9]}}, align 4 ! LLVMIR: %[[urem:.*]] = urem i32 %[[i4]], 4 ! LLVMIR-BE: %[[s:.*]] = sub i32 3, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <4 x i32> %[[x]], i32 %[[v]], i32 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <4 x i32> %[[x]], i32 %[[v]], i32 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i32 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i32 %[[urem]] to i64 +! LLVMIR: %[[r:.*]] = insertelement <4 x i32> %[[x]], i32 %[[v]], i64 %[[idx]] ! LLVMIR: store <4 x i32> %[[r]], ptr %{{[0-9]}}, align 16 r = vec_insert(v, x, i8) @@ -267,10 +282,10 @@ subroutine vec_insert_testi32(v, x, i1, i2, i4, i8) ! LLVMIR: %[[v:.*]] = load i32, ptr %{{[0-9]}}, align 4 ! LLVMIR: %[[x:.*]] = load <4 x i32>, ptr %{{[0-9]}}, align 16 ! LLVMIR: %[[i8:.*]] = load i64, ptr %{{[0-9]}}, align 8 -! LLVMIR: %[[urem:.*]] = urem i64 %[[i8]], 4 -! LLVMIR-BE: %[[s:.*]] = sub i64 3, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <4 x i32> %[[x]], i32 %[[v]], i64 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <4 x i32> %[[x]], i32 %[[v]], i64 %[[s]] +! LLVMIR-BE: %[[urem:.*]] = urem i64 %[[i8]], 4 +! LLVMIR-BE: %[[idx:.*]] = sub i64 3, %[[urem]] +! LLVMIR-LE: %[[idx:.*]] = urem i64 %[[i8]], 4 +! LLVMIR: %[[r:.*]] = insertelement <4 x i32> %[[x]], i32 %[[v]], i64 %[[idx]] ! LLVMIR: store <4 x i32> %[[r]], ptr %{{[0-9]}}, align 16 end subroutine vec_insert_testi32 @@ -290,8 +305,9 @@ subroutine vec_insert_testi64(v, x, i1, i2, i4, i8) ! LLVMIR: %[[i1:.*]] = load i8, ptr %{{[0-9]}}, align 1 ! LLVMIR: %[[urem:.*]] = urem i8 %[[i1]], 2 ! LLVMIR-BE: %[[s:.*]] = sub i8 1, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <2 x i64> %[[x]], i64 %[[v]], i8 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <2 x i64> %[[x]], i64 %[[v]], i8 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i8 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i8 %[[urem]] to i64 +! LLVMIR: %[[r:.*]] = insertelement <2 x i64> %[[x]], i64 %[[v]], i64 %[[idx]] ! LLVMIR: store <2 x i64> %[[r]], ptr %{{[0-9]}}, align 16 r = vec_insert(v, x, i2) @@ -301,8 +317,9 @@ subroutine vec_insert_testi64(v, x, i1, i2, i4, i8) ! LLVMIR: %[[i2:.*]] = load i16, ptr %{{[0-9]}}, align 2 ! LLVMIR: %[[urem:.*]] = urem i16 %[[i2]], 2 ! LLVMIR-BE: %[[s:.*]] = sub i16 1, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <2 x i64> %[[x]], i64 %[[v]], i16 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <2 x i64> %[[x]], i64 %[[v]], i16 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i16 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i16 %[[urem]] to i64 +! LLVMIR: %[[r:.*]] = insertelement <2 x i64> %[[x]], i64 %[[v]], i64 %[[idx]] ! LLVMIR: store <2 x i64> %[[r]], ptr %{{[0-9]}}, align 16 r = vec_insert(v, x, i4) @@ -312,8 +329,9 @@ subroutine vec_insert_testi64(v, x, i1, i2, i4, i8) ! LLVMIR: %[[i4:.*]] = load i32, ptr %{{[0-9]}}, align 4 ! LLVMIR: %[[urem:.*]] = urem i32 %[[i4]], 2 ! LLVMIR-BE: %[[s:.*]] = sub i32 1, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <2 x i64> %[[x]], i64 %[[v]], i32 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <2 x i64> %[[x]], i64 %[[v]], i32 %[[s]] +! LLVMIR-BE: %[[idx:.*]] = zext i32 %[[s]] to i64 +! LLVMIR-LE: %[[idx:.*]] = zext i32 %[[urem]] to i64 +! LLVMIR: %[[r:.*]] = insertelement <2 x i64> %[[x]], i64 %[[v]], i64 %[[idx]] ! LLVMIR: store <2 x i64> %[[r]], ptr %{{[0-9]}}, align 16 r = vec_insert(v, x, i8) @@ -321,9 +339,9 @@ subroutine vec_insert_testi64(v, x, i1, i2, i4, i8) ! LLVMIR: %[[v:.*]] = load i64, ptr %{{[0-9]}}, align 8 ! LLVMIR: %[[x:.*]] = load <2 x i64>, ptr %{{[0-9]}}, align 16 ! LLVMIR: %[[i8:.*]] = load i64, ptr %{{[0-9]}}, align 8 -! LLVMIR: %[[urem:.*]] = urem i64 %[[i8]], 2 -! LLVMIR-BE: %[[s:.*]] = sub i64 1, %[[urem]] -! LLVMIR-LE: %[[r:.*]] = insertelement <2 x i64> %[[x]], i64 %[[v]], i64 %[[urem]] -! LLVMIR-BE: %[[r:.*]] = insertelement <2 x i64> %[[x]], i64 %[[v]], i64 %[[s]] +! LLVMIR-BE: %[[urem:.*]] = urem i64 %[[i8]], 2 +! LLVMIR-BE: %[[idx:.*]] = sub i64 1, %[[urem]] +! LLVMIR-LE: %[[idx:.*]] = urem i64 %[[i8]], 2 +! LLVMIR: %[[r:.*]] = insertelement <2 x i64> %[[x]], i64 %[[v]], i64 %[[idx]] ! LLVMIR: store <2 x i64> %[[r]], ptr %{{[0-9]}}, align 16 end subroutine vec_insert_testi64 diff --git a/flang/test/Lower/PowerPC/ppc-vec-splat-elem-order.f90 b/flang/test/Lower/PowerPC/ppc-vec-splat-elem-order.f90 index 50604e1f720f3..ca8c0c3f6f1d8 100644 --- a/flang/test/Lower/PowerPC/ppc-vec-splat-elem-order.f90 +++ b/flang/test/Lower/PowerPC/ppc-vec-splat-elem-order.f90 @@ -19,7 +19,7 @@ subroutine vec_splat_testu8i16(x) y = vec_splat(x, 0_2) ! LLVMIR: %[[x:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 -! LLVMIR: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i16 15 +! LLVMIR: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i64 15 ! LLVMIR: %[[ins:.*]] = insertelement <16 x i8> poison, i8 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <16 x i8> %[[ins]], <16 x i8> poison, <16 x i32> zeroinitializer ! LLVMIR: store <16 x i8> %[[y]], ptr %{{[0-9]}}, align 16 diff --git a/flang/test/Lower/PowerPC/ppc-vec-splat.f90 b/flang/test/Lower/PowerPC/ppc-vec-splat.f90 index f3c1f19d5877d..55614c75d1ad8 100644 --- a/flang/test/Lower/PowerPC/ppc-vec-splat.f90 +++ b/flang/test/Lower/PowerPC/ppc-vec-splat.f90 @@ -1,5 +1,5 @@ -! RUN: %flang_fc1 -flang-experimental-hlfir -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefixes="LLVMIR","LLVMIR-LE" %s -! RUN: %flang_fc1 -flang-experimental-hlfir -triple powerpc64-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefixes="LLVMIR","LLVMIR-BE" %s +! RUN: %flang_fc1 -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefixes="LLVMIR","LLVMIR-LE" %s +! RUN: %flang_fc1 -triple powerpc64-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefixes="LLVMIR","LLVMIR-BE" %s ! REQUIRES: target=powerpc{{.*}} !---------------- @@ -12,8 +12,8 @@ subroutine vec_splat_testi8i8(x) y = vec_splat(x, 0_1) ! LLVMIR: %[[x:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i8 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i8 15 +! LLVMIR-LE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i64 15 ! LLVMIR: %[[ins:.*]] = insertelement <16 x i8> poison, i8 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <16 x i8> %[[ins]], <16 x i8> poison, <16 x i32> zeroinitializer ! LLVMIR: store <16 x i8> %[[y]], ptr %{{[0-9]}}, align 16 @@ -25,8 +25,8 @@ subroutine vec_splat_testi8i16(x) y = vec_splat(x, 0_2) ! LLVMIR: %[[x:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i16 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i16 15 +! LLVMIR-LE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i64 15 ! LLVMIR: %[[ins:.*]] = insertelement <16 x i8> poison, i8 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <16 x i8> %[[ins]], <16 x i8> poison, <16 x i32> zeroinitializer ! LLVMIR: store <16 x i8> %[[y]], ptr %{{[0-9]}}, align 16 @@ -38,8 +38,8 @@ subroutine vec_splat_testi8i32(x) y = vec_splat(x, 0_4) ! LLVMIR: %[[x:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i32 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i32 15 +! LLVMIR-LE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i64 15 ! LLVMIR: %[[ins:.*]] = insertelement <16 x i8> poison, i8 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <16 x i8> %[[ins]], <16 x i8> poison, <16 x i32> zeroinitializer ! LLVMIR: store <16 x i8> %[[y]], ptr %{{[0-9]}}, align 16 @@ -64,8 +64,8 @@ subroutine vec_splat_testi16i8(x) y = vec_splat(x, 0_1) ! LLVMIR: %[[x:.*]] = load <8 x i16>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i8 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i8 7 +! LLVMIR-LE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i64 7 ! LLVMIR: %[[ins:.*]] = insertelement <8 x i16> poison, i16 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <8 x i16> %[[ins]], <8 x i16> poison, <8 x i32> zeroinitializer ! LLVMIR: store <8 x i16> %[[y]], ptr %{{[0-9]}}, align 16 @@ -77,8 +77,8 @@ subroutine vec_splat_testi16i16(x) y = vec_splat(x, 0_2) ! LLVMIR: %[[x:.*]] = load <8 x i16>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i16 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i16 7 +! LLVMIR-LE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i64 7 ! LLVMIR: %[[ins:.*]] = insertelement <8 x i16> poison, i16 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <8 x i16> %[[ins]], <8 x i16> poison, <8 x i32> zeroinitializer ! LLVMIR: store <8 x i16> %[[y]], ptr %{{[0-9]}}, align 16 @@ -90,8 +90,8 @@ subroutine vec_splat_testi16i32(x) y = vec_splat(x, 0_4) ! LLVMIR: %[[x:.*]] = load <8 x i16>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i32 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i32 7 +! LLVMIR-LE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i64 7 ! LLVMIR: %[[ins:.*]] = insertelement <8 x i16> poison, i16 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <8 x i16> %[[ins]], <8 x i16> poison, <8 x i32> zeroinitializer ! LLVMIR: store <8 x i16> %[[y]], ptr %{{[0-9]}}, align 16 @@ -116,8 +116,8 @@ subroutine vec_splat_testi32i8(x) y = vec_splat(x, 0_1) ! LLVMIR: %[[x:.*]] = load <4 x i32>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i8 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i8 3 +! LLVMIR-LE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i64 3 ! LLVMIR: %[[ins:.*]] = insertelement <4 x i32> poison, i32 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <4 x i32> %[[ins]], <4 x i32> poison, <4 x i32> zeroinitializer ! LLVMIR: store <4 x i32> %[[y]], ptr %{{[0-9]}}, align 16 @@ -129,8 +129,8 @@ subroutine vec_splat_testi32i16(x) y = vec_splat(x, 0_2) ! LLVMIR: %[[x:.*]] = load <4 x i32>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i16 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i16 3 +! LLVMIR-LE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i64 3 ! LLVMIR: %[[ins:.*]] = insertelement <4 x i32> poison, i32 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <4 x i32> %[[ins]], <4 x i32> poison, <4 x i32> zeroinitializer ! LLVMIR: store <4 x i32> %[[y]], ptr %{{[0-9]}}, align 16 @@ -142,8 +142,8 @@ subroutine vec_splat_testi32i32(x) y = vec_splat(x, 0_4) ! LLVMIR: %[[x:.*]] = load <4 x i32>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i32 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i32 3 +! LLVMIR-LE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i64 3 ! LLVMIR: %[[ins:.*]] = insertelement <4 x i32> poison, i32 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <4 x i32> %[[ins]], <4 x i32> poison, <4 x i32> zeroinitializer ! LLVMIR: store <4 x i32> %[[y]], ptr %{{[0-9]}}, align 16 @@ -168,8 +168,8 @@ subroutine vec_splat_testi64i8(x) y = vec_splat(x, 0_1) ! LLVMIR: %[[x:.*]] = load <2 x i64>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i8 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i8 1 +! LLVMIR-LE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i64 1 ! LLVMIR: %[[ins:.*]] = insertelement <2 x i64> poison, i64 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <2 x i64> %[[ins]], <2 x i64> poison, <2 x i32> zeroinitializer ! LLVMIR: store <2 x i64> %[[y]], ptr %{{[0-9]}}, align 16 @@ -181,8 +181,8 @@ subroutine vec_splat_testi64i16(x) y = vec_splat(x, 0_2) ! LLVMIR: %[[x:.*]] = load <2 x i64>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i16 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i16 1 +! LLVMIR-LE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i64 1 ! LLVMIR: %[[ins:.*]] = insertelement <2 x i64> poison, i64 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <2 x i64> %[[ins]], <2 x i64> poison, <2 x i32> zeroinitializer ! LLVMIR: store <2 x i64> %[[y]], ptr %{{[0-9]}}, align 16 @@ -194,8 +194,8 @@ subroutine vec_splat_testi64i32(x) y = vec_splat(x, 0_4) ! LLVMIR: %[[x:.*]] = load <2 x i64>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i32 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i32 1 +! LLVMIR-LE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i64 1 ! LLVMIR: %[[ins:.*]] = insertelement <2 x i64> poison, i64 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <2 x i64> %[[ins]], <2 x i64> poison, <2 x i32> zeroinitializer ! LLVMIR: store <2 x i64> %[[y]], ptr %{{[0-9]}}, align 16 @@ -220,8 +220,8 @@ subroutine vec_splat_testf32i8(x) y = vec_splat(x, 0_1) ! LLVMIR: %[[x:.*]] = load <4 x float>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <4 x float> %[[x]], i8 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <4 x float> %[[x]], i8 3 +! LLVMIR-LE: %[[ele:.*]] = extractelement <4 x float> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <4 x float> %[[x]], i64 3 ! LLVMIR: %[[ins:.*]] = insertelement <4 x float> poison, float %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <4 x float> %[[ins]], <4 x float> poison, <4 x i32> zeroinitializer ! LLVMIR: store <4 x float> %[[y]], ptr %{{[0-9]}}, align 16 @@ -233,8 +233,8 @@ subroutine vec_splat_testf32i16(x) y = vec_splat(x, 0_2) ! LLVMIR: %[[x:.*]] = load <4 x float>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <4 x float> %[[x]], i16 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <4 x float> %[[x]], i16 3 +! LLVMIR-LE: %[[ele:.*]] = extractelement <4 x float> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <4 x float> %[[x]], i64 3 ! LLVMIR: %[[ins:.*]] = insertelement <4 x float> poison, float %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <4 x float> %[[ins]], <4 x float> poison, <4 x i32> zeroinitializer ! LLVMIR: store <4 x float> %[[y]], ptr %{{[0-9]}}, align 16 @@ -246,8 +246,8 @@ subroutine vec_splat_testf32i32(x) y = vec_splat(x, 0_4) ! LLVMIR: %[[x:.*]] = load <4 x float>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <4 x float> %[[x]], i32 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <4 x float> %[[x]], i32 3 +! LLVMIR-LE: %[[ele:.*]] = extractelement <4 x float> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <4 x float> %[[x]], i64 3 ! LLVMIR: %[[ins:.*]] = insertelement <4 x float> poison, float %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <4 x float> %[[ins]], <4 x float> poison, <4 x i32> zeroinitializer ! LLVMIR: store <4 x float> %[[y]], ptr %{{[0-9]}}, align 16 @@ -272,8 +272,8 @@ subroutine vec_splat_testf64i8(x) y = vec_splat(x, 0_1) ! LLVMIR: %[[x:.*]] = load <2 x double>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <2 x double> %[[x]], i8 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <2 x double> %[[x]], i8 1 +! LLVMIR-LE: %[[ele:.*]] = extractelement <2 x double> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <2 x double> %[[x]], i64 1 ! LLVMIR: %[[ins:.*]] = insertelement <2 x double> poison, double %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <2 x double> %[[ins]], <2 x double> poison, <2 x i32> zeroinitializer ! LLVMIR: store <2 x double> %[[y]], ptr %{{[0-9]}}, align 16 @@ -285,8 +285,8 @@ subroutine vec_splat_testf64i16(x) y = vec_splat(x, 0_2) ! LLVMIR: %[[x:.*]] = load <2 x double>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <2 x double> %[[x]], i16 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <2 x double> %[[x]], i16 1 +! LLVMIR-LE: %[[ele:.*]] = extractelement <2 x double> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <2 x double> %[[x]], i64 1 ! LLVMIR: %[[ins:.*]] = insertelement <2 x double> poison, double %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <2 x double> %[[ins]], <2 x double> poison, <2 x i32> zeroinitializer ! LLVMIR: store <2 x double> %[[y]], ptr %{{[0-9]}}, align 16 @@ -298,8 +298,8 @@ subroutine vec_splat_testf64i32(x) y = vec_splat(x, 0_4) ! LLVMIR: %[[x:.*]] = load <2 x double>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <2 x double> %[[x]], i32 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <2 x double> %[[x]], i32 1 +! LLVMIR-LE: %[[ele:.*]] = extractelement <2 x double> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <2 x double> %[[x]], i64 1 ! LLVMIR: %[[ins:.*]] = insertelement <2 x double> poison, double %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <2 x double> %[[ins]], <2 x double> poison, <2 x i32> zeroinitializer ! LLVMIR: store <2 x double> %[[y]], ptr %{{[0-9]}}, align 16 @@ -324,8 +324,8 @@ subroutine vec_splat_testu8i8(x) y = vec_splat(x, 0_1) ! LLVMIR: %[[x:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i8 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i8 15 +! LLVMIR-LE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i64 15 ! LLVMIR: %[[ins:.*]] = insertelement <16 x i8> poison, i8 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <16 x i8> %[[ins]], <16 x i8> poison, <16 x i32> zeroinitializer ! LLVMIR: store <16 x i8> %[[y]], ptr %{{[0-9]}}, align 16 @@ -337,8 +337,8 @@ subroutine vec_splat_testu8i16(x) y = vec_splat(x, 0_2) ! LLVMIR: %[[x:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i16 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i16 15 +! LLVMIR-LE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i64 15 ! LLVMIR: %[[ins:.*]] = insertelement <16 x i8> poison, i8 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <16 x i8> %[[ins]], <16 x i8> poison, <16 x i32> zeroinitializer ! LLVMIR: store <16 x i8> %[[y]], ptr %{{[0-9]}}, align 16 @@ -350,8 +350,8 @@ subroutine vec_splat_testu8i32(x) y = vec_splat(x, 0_4) ! LLVMIR: %[[x:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i32 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i32 15 +! LLVMIR-LE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <16 x i8> %[[x]], i64 15 ! LLVMIR: %[[ins:.*]] = insertelement <16 x i8> poison, i8 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <16 x i8> %[[ins]], <16 x i8> poison, <16 x i32> zeroinitializer ! LLVMIR: store <16 x i8> %[[y]], ptr %{{[0-9]}}, align 16 @@ -376,8 +376,8 @@ subroutine vec_splat_testu16i8(x) y = vec_splat(x, 0_1) ! LLVMIR: %[[x:.*]] = load <8 x i16>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i8 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i8 7 +! LLVMIR-LE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i64 7 ! LLVMIR: %[[ins:.*]] = insertelement <8 x i16> poison, i16 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <8 x i16> %[[ins]], <8 x i16> poison, <8 x i32> zeroinitializer ! LLVMIR: store <8 x i16> %[[y]], ptr %{{[0-9]}}, align 16 @@ -389,8 +389,8 @@ subroutine vec_splat_testu16i16(x) y = vec_splat(x, 0_2) ! LLVMIR: %[[x:.*]] = load <8 x i16>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i16 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i16 7 +! LLVMIR-LE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i64 7 ! LLVMIR: %[[ins:.*]] = insertelement <8 x i16> poison, i16 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <8 x i16> %[[ins]], <8 x i16> poison, <8 x i32> zeroinitializer ! LLVMIR: store <8 x i16> %[[y]], ptr %{{[0-9]}}, align 16 @@ -402,8 +402,8 @@ subroutine vec_splat_testu16i32(x) y = vec_splat(x, 0_4) ! LLVMIR: %[[x:.*]] = load <8 x i16>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i32 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i32 7 +! LLVMIR-LE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <8 x i16> %[[x]], i64 7 ! LLVMIR: %[[ins:.*]] = insertelement <8 x i16> poison, i16 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <8 x i16> %[[ins]], <8 x i16> poison, <8 x i32> zeroinitializer ! LLVMIR: store <8 x i16> %[[y]], ptr %{{[0-9]}}, align 16 @@ -428,8 +428,8 @@ subroutine vec_splat_testu32i8(x) y = vec_splat(x, 0_1) ! LLVMIR: %[[x:.*]] = load <4 x i32>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i8 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i8 3 +! LLVMIR-LE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i64 3 ! LLVMIR: %[[ins:.*]] = insertelement <4 x i32> poison, i32 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <4 x i32> %[[ins]], <4 x i32> poison, <4 x i32> zeroinitializer ! LLVMIR: store <4 x i32> %[[y]], ptr %{{[0-9]}}, align 16 @@ -441,8 +441,8 @@ subroutine vec_splat_testu32i16(x) y = vec_splat(x, 0_2) ! LLVMIR: %[[x:.*]] = load <4 x i32>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i16 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i16 3 +! LLVMIR-LE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i64 3 ! LLVMIR: %[[ins:.*]] = insertelement <4 x i32> poison, i32 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <4 x i32> %[[ins]], <4 x i32> poison, <4 x i32> zeroinitializer ! LLVMIR: store <4 x i32> %[[y]], ptr %{{[0-9]}}, align 16 @@ -454,8 +454,8 @@ subroutine vec_splat_testu32i32(x) y = vec_splat(x, 0_4) ! LLVMIR: %[[x:.*]] = load <4 x i32>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i32 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i32 3 +! LLVMIR-LE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <4 x i32> %[[x]], i64 3 ! LLVMIR: %[[ins:.*]] = insertelement <4 x i32> poison, i32 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <4 x i32> %[[ins]], <4 x i32> poison, <4 x i32> zeroinitializer ! LLVMIR: store <4 x i32> %[[y]], ptr %{{[0-9]}}, align 16 @@ -480,8 +480,8 @@ subroutine vec_splat_testu64i8(x) y = vec_splat(x, 0_1) ! LLVMIR: %[[x:.*]] = load <2 x i64>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i8 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i8 1 +! LLVMIR-LE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i64 1 ! LLVMIR: %[[ins:.*]] = insertelement <2 x i64> poison, i64 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <2 x i64> %[[ins]], <2 x i64> poison, <2 x i32> zeroinitializer ! LLVMIR: store <2 x i64> %[[y]], ptr %{{[0-9]}}, align 16 @@ -493,8 +493,8 @@ subroutine vec_splat_testu64i16(x) y = vec_splat(x, 0_2) ! LLVMIR: %[[x:.*]] = load <2 x i64>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i16 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i16 1 +! LLVMIR-LE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i64 1 ! LLVMIR: %[[ins:.*]] = insertelement <2 x i64> poison, i64 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <2 x i64> %[[ins]], <2 x i64> poison, <2 x i32> zeroinitializer ! LLVMIR: store <2 x i64> %[[y]], ptr %{{[0-9]}}, align 16 @@ -506,8 +506,8 @@ subroutine vec_splat_testu64i32(x) y = vec_splat(x, 0_4) ! LLVMIR: %[[x:.*]] = load <2 x i64>, ptr %{{[0-9]}}, align 16 -! LLVMIR-LE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i32 0 -! LLVMIR-BE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i32 1 +! LLVMIR-LE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i64 0 +! LLVMIR-BE: %[[ele:.*]] = extractelement <2 x i64> %[[x]], i64 1 ! LLVMIR: %[[ins:.*]] = insertelement <2 x i64> poison, i64 %[[ele]], i32 0 ! LLVMIR: %[[y:.*]] = shufflevector <2 x i64> %[[ins]], <2 x i64> poison, <2 x i32> zeroinitializer ! LLVMIR: store <2 x i64> %[[y]], ptr %{{[0-9]}}, align 16 diff --git a/flang/test/Lower/amdgcn-complex.f90 b/flang/test/Lower/amdgcn-complex.f90 new file mode 100644 index 0000000000000..f15c7db2b7316 --- /dev/null +++ b/flang/test/Lower/amdgcn-complex.f90 @@ -0,0 +1,21 @@ +! REQUIRES: amdgpu-registered-target +! RUN: %flang_fc1 -triple amdgcn-amd-amdhsa -emit-fir -flang-deprecated-no-hlfir %s -o - | FileCheck %s + +subroutine cabsf_test(a, b) + complex :: a + real :: b + b = abs(a) +end subroutine + +! CHECK-LABEL: func @_QPcabsf_test( +! CHECK: complex.abs +! CHECK-NOT: fir.call @cabsf + +subroutine cexpf_test(a, b) + complex :: a, b + b = exp(a) +end subroutine + +! CHECK-LABEL: func @_QPcexpf_test( +! CHECK: complex.exp +! CHECK-NOT: fir.call @cexpf diff --git a/flang/test/Lower/array-character.f90 b/flang/test/Lower/array-character.f90 index 1bc73dae44235..e2899d967c80d 100644 --- a/flang/test/Lower/array-character.f90 +++ b/flang/test/Lower/array-character.f90 @@ -32,7 +32,7 @@ program p call charlit end program p -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "p"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "P"} { ! CHECK: %[[VAL_0:.*]] = arith.constant 4 : index ! CHECK: %[[VAL_1:.*]] = arith.constant 3 : index ! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.array<3x!fir.char<1,4>> {bindc_name = "c1", uniq_name = "_QFEc1"} diff --git a/flang/test/Lower/array-expression-slice-1.f90 b/flang/test/Lower/array-expression-slice-1.f90 index b597814bc0d9f..73943137cb18d 100644 --- a/flang/test/Lower/array-expression-slice-1.f90 +++ b/flang/test/Lower/array-expression-slice-1.f90 @@ -1,6 +1,6 @@ ! RUN: bbc -hlfir=false -fwrapv -o - --outline-intrinsics %s | FileCheck %s -! CHECK-LABEL: func @_QQmain() attributes {fir.bindc_name = "p"} { +! CHECK-LABEL: func @_QQmain() attributes {fir.bindc_name = "P"} { ! CHECK-DAG: %[[VAL_0:.*]] = arith.constant 10 : index ! CHECK-DAG: %[[VAL_4:.*]] = arith.constant 2 : index ! CHECK-DAG: %[[VAL_5:.*]] = arith.constant 1 : index diff --git a/flang/test/Lower/basic-program.f90 b/flang/test/Lower/basic-program.f90 index 5a0e4bdc7b4a1..7e5b40d9e2f0a 100644 --- a/flang/test/Lower/basic-program.f90 +++ b/flang/test/Lower/basic-program.f90 @@ -4,10 +4,10 @@ program basic end program -! CHECK: 1 Program basic +! CHECK: 1 Program BASIC ! CHECK: 1 EndProgramStmt: end program -! CHECK: End Program basic +! CHECK: End Program BASIC -! FIR-LABEL: func @_QQmain() attributes {fir.bindc_name = "basic"} { +! FIR-LABEL: func @_QQmain() attributes {fir.bindc_name = "BASIC"} { ! FIR: return ! FIR: } diff --git a/flang/test/Lower/big-integer-parameter.f90 b/flang/test/Lower/big-integer-parameter.f90 index a413b1224ebc2..ca90b8adfb318 100644 --- a/flang/test/Lower/big-integer-parameter.f90 +++ b/flang/test/Lower/big-integer-parameter.f90 @@ -13,7 +13,7 @@ program i128 print*,y end -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "i128"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "I128"} { ! CHECK-COUNT-2: %{{.*}} = fir.call @_FortranAioOutputInteger128(%{{.*}}, %{{.*}}) {{.*}}: (!fir.ref, i128) -> i1 diff --git a/flang/test/Lower/derived-type-finalization.f90 b/flang/test/Lower/derived-type-finalization.f90 index 3ea58cd719f4a..71cef34899603 100644 --- a/flang/test/Lower/derived-type-finalization.f90 +++ b/flang/test/Lower/derived-type-finalization.f90 @@ -255,5 +255,5 @@ program p type(t1) :: t end program -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "p"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "P"} { ! CHECK-NOT: fir.call @_FortranADestroy diff --git a/flang/test/Lower/forall/character-1.f90 b/flang/test/Lower/forall/character-1.f90 index 1e4bb73350871..d1e12a8dbdfec 100644 --- a/flang/test/Lower/forall/character-1.f90 +++ b/flang/test/Lower/forall/character-1.f90 @@ -29,7 +29,9 @@ end program test ! CHECK: %[[esval:.*]] = load i64, ptr %[[elesize]] ! CHECK: %[[mul:.*]] = mul i64 1, %[[esval]] ! CHECK: %[[mul2:.*]] = mul i64 %[[mul]], %[[extval]] -! CHECK: %[[buff:.*]] = call ptr @malloc(i64 %[[mul2]]) +! CHECK: %[[cmp:.*]] = icmp sgt i64 %[[mul2]], 0 +! CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[mul2]], i64 1 +! CHECK: %[[buff:.*]] = call ptr @malloc(i64 %[[size]]) ! CHECK: %[[to:.*]] = getelementptr i8, ptr %[[buff]], i64 % ! CHECK: call void @llvm.memmove.p0.p0.i64(ptr %[[to]], ptr %{{.*}}, i64 %{{.*}}, i1 false) ! CHECK: call void @free(ptr %[[buff]]) diff --git a/flang/test/Lower/io-derived-type.f90 b/flang/test/Lower/io-derived-type.f90 index 7d2fef3faa2b7..7c289ce261678 100644 --- a/flang/test/Lower/io-derived-type.f90 +++ b/flang/test/Lower/io-derived-type.f90 @@ -37,16 +37,16 @@ subroutine test1 import, all ! CHECK: %[[V_16:[0-9]+]] = fir.embox %{{.*}} : (!fir.ref>) -> !fir.box> ! CHECK: %[[V_17:[0-9]+]] = fir.convert %[[V_16]] : (!fir.box>) -> !fir.box - ! CHECK: %[[V_18:[0-9]+]] = fir.address_of(@_QQMmFtest1.nonTbpDefinedIoTable) : !fir.ref, !fir.ref, i32, i1>>>, i1>> - ! CHECK: %[[V_19:[0-9]+]] = fir.convert %[[V_18]] : (!fir.ref, !fir.ref, i32, i1>>>, i1>>) -> !fir.ref + ! CHECK: %[[V_18:[0-9]+]] = fir.address_of(@_QQMmFtest1.nonTbpDefinedIoTable) : !fir.ref, !fir.ref, i32, i8>>>, i1>> + ! CHECK: %[[V_19:[0-9]+]] = fir.convert %[[V_18]] : (!fir.ref, !fir.ref, i32, i8>>>, i1>>) -> !fir.ref ! CHECK: %[[V_20:[0-9]+]] = fir.call @_FortranAioOutputDerivedType(%{{.*}}, %[[V_17]], %[[V_19]]) fastmath : (!fir.ref, !fir.box, !fir.ref) -> i1 print *, 'test1 outer, should call wft: ', t(1) block import, only: t ! CHECK: %[[V_37:[0-9]+]] = fir.embox %{{.*}} : (!fir.ref>) -> !fir.box> ! CHECK: %[[V_38:[0-9]+]] = fir.convert %[[V_37]] : (!fir.box>) -> !fir.box - ! CHECK: %[[V_39:[0-9]+]] = fir.address_of(@_QQdefault.nonTbpDefinedIoTable) : !fir.ref, !fir.ref, i32, i1>>>, i1>> - ! CHECK: %[[V_40:[0-9]+]] = fir.convert %[[V_39]] : (!fir.ref, !fir.ref, i32, i1>>>, i1>>) -> !fir.ref + ! CHECK: %[[V_39:[0-9]+]] = fir.address_of(@_QQdefault.nonTbpDefinedIoTable) : !fir.ref, !fir.ref, i32, i8>>>, i1>> + ! CHECK: %[[V_40:[0-9]+]] = fir.convert %[[V_39]] : (!fir.ref, !fir.ref, i32, i8>>>, i1>>) -> !fir.ref ! CHECK: %[[V_41:[0-9]+]] = fir.call @_FortranAioOutputDerivedType(%{{.*}}, %[[V_38]], %[[V_40]]) fastmath : (!fir.ref, !fir.box, !fir.ref) -> i1 print *, 'test1 block, should not call wft: ', t(2) end block @@ -56,8 +56,8 @@ subroutine test1 subroutine test2 ! CHECK: %[[V_15:[0-9]+]] = fir.embox %{{.*}} : (!fir.ref>) -> !fir.box> ! CHECK: %[[V_16:[0-9]+]] = fir.convert %[[V_15]] : (!fir.box>) -> !fir.box - ! CHECK: %[[V_17:[0-9]+]] = fir.address_of(@_QQdefault.nonTbpDefinedIoTable) : !fir.ref, !fir.ref, i32, i1>>>, i1>> - ! CHECK: %[[V_18:[0-9]+]] = fir.convert %[[V_17]] : (!fir.ref, !fir.ref, i32, i1>>>, i1>>) -> !fir.ref + ! CHECK: %[[V_17:[0-9]+]] = fir.address_of(@_QQdefault.nonTbpDefinedIoTable) : !fir.ref, !fir.ref, i32, i8>>>, i1>> + ! CHECK: %[[V_18:[0-9]+]] = fir.convert %[[V_17]] : (!fir.ref, !fir.ref, i32, i8>>>, i1>>) -> !fir.ref ! CHECK: %[[V_19:[0-9]+]] = fir.call @_FortranAioOutputDerivedType(%{{.*}}, %[[V_16]], %[[V_18]]) fastmath : (!fir.ref, !fir.box, !fir.ref) -> i1 import, only: t @@ -74,23 +74,23 @@ subroutine test3(p, x) ! CHECK: %[[V_3:[0-9]+]] = fir.embox %{{.*}} : (!fir.ref>) -> !fir.box> ! CHECK: %[[V_4:[0-9]+]] = fir.convert %[[V_3]] : (!fir.box>) -> !fir.box - ! CHECK: %[[V_5:[0-9]+]] = fir.alloca !fir.array<1xtuple, !fir.ref, i32, i1>> - ! CHECK: %[[V_6:[0-9]+]] = fir.undefined !fir.array<1xtuple, !fir.ref, i32, i1>> + ! CHECK: %[[V_5:[0-9]+]] = fir.alloca !fir.array<1xtuple, !fir.ref, i32, i8>> + ! CHECK: %[[V_6:[0-9]+]] = fir.undefined !fir.array<1xtuple, !fir.ref, i32, i8>> ! CHECK: %[[V_7:[0-9]+]] = fir.address_of(@_QMmE.dt.t) ! CHECK: %[[V_8:[0-9]+]] = fir.convert %[[V_7]] : {{.*}} -> !fir.ref - ! CHECK: %[[V_9:[0-9]+]] = fir.insert_value %[[V_6]], %[[V_8]], [0 : index, 0 : index] : (!fir.array<1xtuple, !fir.ref, i32, i1>>, !fir.ref) -> !fir.array<1xtuple, !fir.ref, i32, i1>> + ! CHECK: %[[V_9:[0-9]+]] = fir.insert_value %[[V_6]], %[[V_8]], [0 : index, 0 : index] : (!fir.array<1xtuple, !fir.ref, i32, i8>>, !fir.ref) -> !fir.array<1xtuple, !fir.ref, i32, i8>> ! CHECK: %[[V_10:[0-9]+]] = fir.box_addr %arg0 : (!fir.boxproc<() -> ()>) -> !fir.ref - ! CHECK: %[[V_11:[0-9]+]] = fir.insert_value %[[V_9]], %[[V_10]], [0 : index, 1 : index] : (!fir.array<1xtuple, !fir.ref, i32, i1>>, !fir.ref) -> !fir.array<1xtuple, !fir.ref, i32, i1>> - ! CHECK: %[[V_12:[0-9]+]] = fir.insert_value %[[V_11]], %c2{{.*}}, [0 : index, 2 : index] : (!fir.array<1xtuple, !fir.ref, i32, i1>>, i32) -> !fir.array<1xtuple, !fir.ref, i32, i1>> - ! CHECK: %[[V_13:[0-9]+]] = fir.insert_value %[[V_12]], %true, [0 : index, 3 : index] : (!fir.array<1xtuple, !fir.ref, i32, i1>>, i1) -> !fir.array<1xtuple, !fir.ref, i32, i1>> - ! CHECK: fir.store %[[V_13]] to %[[V_5]] : !fir.ref, !fir.ref, i32, i1>>> - ! CHECK: %[[V_14:[0-9]+]] = fir.alloca tuple, !fir.ref, i32, i1>>>, i1> - ! CHECK: %[[V_15:[0-9]+]] = fir.undefined tuple, !fir.ref, i32, i1>>>, i1> - ! CHECK: %[[V_16:[0-9]+]] = fir.insert_value %[[V_15]], %c1{{.*}}, [0 : index] : (tuple, !fir.ref, i32, i1>>>, i1>, i64) -> tuple, !fir.ref, i32, i1>>>, i1> - ! CHECK: %[[V_17:[0-9]+]] = fir.insert_value %[[V_16]], %[[V_5]], [1 : index] : (tuple, !fir.ref, i32, i1>>>, i1>, !fir.ref, !fir.ref, i32, i1>>>) -> tuple, !fir.ref, i32, i1>>>, i1> - ! CHECK: %[[V_18:[0-9]+]] = fir.insert_value %[[V_17]], %true_0, [2 : index] : (tuple, !fir.ref, i32, i1>>>, i1>, i1) -> tuple, !fir.ref, i32, i1>>>, i1> - ! CHECK: fir.store %[[V_18]] to %[[V_14]] : !fir.ref, !fir.ref, i32, i1>>>, i1>> - ! CHECK: %[[V_19:[0-9]+]] = fir.convert %[[V_14]] : (!fir.ref, !fir.ref, i32, i1>>>, i1>>) -> !fir.ref + ! CHECK: %[[V_11:[0-9]+]] = fir.insert_value %[[V_9]], %[[V_10]], [0 : index, 1 : index] : (!fir.array<1xtuple, !fir.ref, i32, i8>>, !fir.ref) -> !fir.array<1xtuple, !fir.ref, i32, i8>> + ! CHECK: %[[V_12:[0-9]+]] = fir.insert_value %[[V_11]], %c2{{.*}}, [0 : index, 2 : index] : (!fir.array<1xtuple, !fir.ref, i32, i8>>, i32) -> !fir.array<1xtuple, !fir.ref, i32, i8>> + ! CHECK: %[[V_13:[0-9]+]] = fir.insert_value %[[V_12]], %c1_i8, [0 : index, 3 : index] : (!fir.array<1xtuple, !fir.ref, i32, i8>>, i8) -> !fir.array<1xtuple, !fir.ref, i32, i8>> + ! CHECK: fir.store %[[V_13]] to %[[V_5]] : !fir.ref, !fir.ref, i32, i8>>> + ! CHECK: %[[V_14:[0-9]+]] = fir.alloca tuple, !fir.ref, i32, i8>>>, i1> + ! CHECK: %[[V_15:[0-9]+]] = fir.undefined tuple, !fir.ref, i32, i8>>>, i1> + ! CHECK: %[[V_16:[0-9]+]] = fir.insert_value %[[V_15]], %c1{{.*}}, [0 : index] : (tuple, !fir.ref, i32, i8>>>, i1>, i64) -> tuple, !fir.ref, i32, i8>>>, i1> + ! CHECK: %[[V_17:[0-9]+]] = fir.insert_value %[[V_16]], %[[V_5]], [1 : index] : (tuple, !fir.ref, i32, i8>>>, i1>, !fir.ref, !fir.ref, i32, i8>>>) -> tuple, !fir.ref, i32, i8>>>, i1> + ! CHECK: %[[V_18:[0-9]+]] = fir.insert_value %[[V_17]], %true, [2 : index] : (tuple, !fir.ref, i32, i8>>>, i1>, i1) -> tuple, !fir.ref, i32, i8>>>, i1> + ! CHECK: fir.store %[[V_18]] to %[[V_14]] : !fir.ref, !fir.ref, i32, i8>>>, i1>> + ! CHECK: %[[V_19:[0-9]+]] = fir.convert %[[V_14]] : (!fir.ref, !fir.ref, i32, i8>>>, i1>>) -> !fir.ref ! CHECK: %[[V_20:[0-9]+]] = fir.call @_FortranAioOutputDerivedType(%{{.*}}, %[[V_4]], %[[V_19]]) fastmath : (!fir.ref, !fir.box, !fir.ref) -> i1 print *, x end subroutine @@ -112,8 +112,8 @@ program p ! CHECK: %[[V_97:[0-9]+]] = fir.embox %{{.*}} : (!fir.ref>) -> !fir.box> ! CHECK: %[[V_98:[0-9]+]] = fir.convert %[[V_97]] : (!fir.box>) -> !fir.box - ! CHECK: %[[V_99:[0-9]+]] = fir.address_of(@_QQF.nonTbpDefinedIoTable) : !fir.ref, !fir.ref, i32, i1>>>, i1>> - ! CHECK: %[[V_100:[0-9]+]] = fir.convert %[[V_99]] : (!fir.ref, !fir.ref, i32, i1>>>, i1>>) -> !fir.ref + ! CHECK: %[[V_99:[0-9]+]] = fir.address_of(@_QQF.nonTbpDefinedIoTable) : !fir.ref, !fir.ref, i32, i8>>>, i1>> + ! CHECK: %[[V_100:[0-9]+]] = fir.convert %[[V_99]] : (!fir.ref, !fir.ref, i32, i8>>>, i1>>) -> !fir.ref ! CHECK: %[[V_101:[0-9]+]] = fir.call @_FortranAioOutputDerivedType(%{{.*}}, %[[V_98]], %[[V_100]]) fastmath : (!fir.ref, !fir.box, !fir.ref) -> i1 print *, 'main, should call wft: ', t(4) @@ -122,14 +122,14 @@ program p ! CHECK: %[[V_35:[0-9]+]] = fir.shape %c2{{.*}} : (index) -> !fir.shape<1> ! CHECK: %[[V_36:[0-9]+]] = fir.embox %[[V_34]](%[[V_35]]) : (!fir.ref>>, !fir.shape<1>) -> !fir.box>> ! CHECK: %[[V_37:[0-9]+]] = fir.convert %[[V_36]] : (!fir.box>>) -> !fir.box - ! CHECK: %[[V_38:[0-9]+]] = fir.address_of(@_QQF.nonTbpDefinedIoTable) : !fir.ref, !fir.ref, i32, i1>>>, i1>> - ! CHECK: %[[V_39:[0-9]+]] = fir.convert %[[V_38]] : (!fir.ref, !fir.ref, i32, i1>>>, i1>>) -> !fir.ref + ! CHECK: %[[V_38:[0-9]+]] = fir.address_of(@_QQF.nonTbpDefinedIoTable) : !fir.ref, !fir.ref, i32, i8>>>, i1>> + ! CHECK: %[[V_39:[0-9]+]] = fir.convert %[[V_38]] : (!fir.ref, !fir.ref, i32, i8>>>, i1>>) -> !fir.ref ! CHECK: %[[V_40:[0-9]+]] = fir.call @_FortranAioOutputDerivedType(%{{.*}}, %[[V_37]], %[[V_39]]) fastmath : (!fir.ref, !fir.box, !fir.ref) -> i1 print *, y(2:3) end -! CHECK: fir.global linkonce @_QQMmFtest1.nonTbpDefinedIoTable.list constant : !fir.array<1xtuple, !fir.ref, i32, i1>> -! CHECK: fir.global linkonce @_QQMmFtest1.nonTbpDefinedIoTable constant : tuple, !fir.ref, i32, i1>>>, i1> -! CHECK: fir.global linkonce @_QQdefault.nonTbpDefinedIoTable constant : tuple, !fir.ref, i32, i1>>>, i1> -! CHECK: fir.global linkonce @_QQF.nonTbpDefinedIoTable.list constant : !fir.array<1xtuple, !fir.ref, i32, i1>> -! CHECK: fir.global linkonce @_QQF.nonTbpDefinedIoTable constant : tuple, !fir.ref, i32, i1>>>, i1> +! CHECK: fir.global linkonce @_QQMmFtest1.nonTbpDefinedIoTable.list constant : !fir.array<1xtuple, !fir.ref, i32, i8>> +! CHECK: fir.global linkonce @_QQMmFtest1.nonTbpDefinedIoTable constant : tuple, !fir.ref, i32, i8>>>, i1> +! CHECK: fir.global linkonce @_QQdefault.nonTbpDefinedIoTable constant : tuple, !fir.ref, i32, i8>>>, i1> +! CHECK: fir.global linkonce @_QQF.nonTbpDefinedIoTable.list constant : !fir.array<1xtuple, !fir.ref, i32, i8>> +! CHECK: fir.global linkonce @_QQF.nonTbpDefinedIoTable constant : tuple, !fir.ref, i32, i8>>>, i1> diff --git a/flang/test/Lower/location.f90 b/flang/test/Lower/location.f90 index a6ece31bbebed..95bf2260fc107 100644 --- a/flang/test/Lower/location.f90 +++ b/flang/test/Lower/location.f90 @@ -5,7 +5,7 @@ program test end -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "test"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "TEST"} { ! CHECK: fir.call @_FortranAioOutputAscii(%{{.*}}, %{{.*}}, %{{.*}}) fastmath : (!fir.ref, !fir.ref, i64) -> i1 loc(fused<#fir>["{{.*}}location1.inc":1:10, "{{.*}}location0.inc":1:1, "{{.*}}location.f90":4:1]) ! CHECK: return loc("{{.*}}location.f90":6:1) ! CHECK: } loc("{{.*}}location.f90":3:1) diff --git a/flang/test/Lower/namelist.f90 b/flang/test/Lower/namelist.f90 index 94b0ef11cb102..770af46eea744 100644 --- a/flang/test/Lower/namelist.f90 +++ b/flang/test/Lower/namelist.f90 @@ -42,8 +42,8 @@ program p ! CHECK: %[[V_42:[0-9]+]] = fir.insert_value %[[V_39]], %[[V_41]], [0 : index] : (tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref>, !fir.ref) -> tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> ! CHECK: %[[V_43:[0-9]+]] = fir.insert_value %[[V_42]], %c2{{.*}}, [1 : index] : (tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref>, i64) -> tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> ! CHECK: %[[V_44:[0-9]+]] = fir.insert_value %[[V_43]], %[[V_24]], [2 : index] : (tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref>, !fir.ref, !fir.ref>>>>) -> tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> - ! CHECK: %[[V_45:[0-9]+]] = fir.address_of(@_QQdefault.nonTbpDefinedIoTable) : !fir.ref, !fir.ref, i32, i1>>>, i1>> - ! CHECK: %[[V_46:[0-9]+]] = fir.convert %[[V_45]] : (!fir.ref, !fir.ref, i32, i1>>>, i1>>) -> !fir.ref + ! CHECK: %[[V_45:[0-9]+]] = fir.address_of(@_QQdefault.nonTbpDefinedIoTable) : !fir.ref, !fir.ref, i32, i8>>>, i1>> + ! CHECK: %[[V_46:[0-9]+]] = fir.convert %[[V_45]] : (!fir.ref, !fir.ref, i32, i8>>>, i1>>) -> !fir.ref ! CHECK: %[[V_47:[0-9]+]] = fir.insert_value %[[V_44]], %[[V_46]], [3 : index] : (tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref>, !fir.ref) -> tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> ! CHECK: fir.store %[[V_47]] to %[[V_38]] : !fir.ref, i64, !fir.ref, !fir.ref>>>>, !fir.ref>> ! CHECK: %[[V_48:[0-9]+]] = fir.convert %[[V_38]] : (!fir.ref, i64, !fir.ref, !fir.ref>>>>, !fir.ref>>) -> !fir.ref> @@ -100,8 +100,8 @@ subroutine sss ! CHECK: %[[V_20:[0-9]+]] = fir.insert_value %[[V_17]], %[[V_19]], [0 : index] : (tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref>, !fir.ref) -> tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> ! CHECK: %[[V_21:[0-9]+]] = fir.insert_value %[[V_20]], %c1{{.*}}, [1 : index] : (tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref>, i64) -> tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> ! CHECK: %[[V_22:[0-9]+]] = fir.insert_value %[[V_21]], %[[V_8]], [2 : index] : (tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref>, !fir.ref, !fir.ref>>>>) -> tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> - ! CHECK: %[[V_23:[0-9]+]] = fir.address_of(@_QQdefault.nonTbpDefinedIoTable) : !fir.ref, !fir.ref, i32, i1>>>, i1>> - ! CHECK: %[[V_24:[0-9]+]] = fir.convert %[[V_23]] : (!fir.ref, !fir.ref, i32, i1>>>, i1>>) -> !fir.ref + ! CHECK: %[[V_23:[0-9]+]] = fir.address_of(@_QQdefault.nonTbpDefinedIoTable) : !fir.ref, !fir.ref, i32, i8>>>, i1>> + ! CHECK: %[[V_24:[0-9]+]] = fir.convert %[[V_23]] : (!fir.ref, !fir.ref, i32, i8>>>, i1>>) -> !fir.ref ! CHECK: %[[V_25:[0-9]+]] = fir.insert_value %[[V_22]], %[[V_24]], [3 : index] : (tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref>, !fir.ref) -> tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> ! CHECK: fir.store %[[V_25]] to %[[V_16]] : !fir.ref, i64, !fir.ref, !fir.ref>>>>, !fir.ref>> ! CHECK: %[[V_26:[0-9]+]] = fir.convert %[[V_16]] : (!fir.ref, i64, !fir.ref, !fir.ref>>>>, !fir.ref>>) -> !fir.ref> diff --git a/flang/test/Lower/nested-where.f90 b/flang/test/Lower/nested-where.f90 index ab457280b80ce..28aced2325813 100644 --- a/flang/test/Lower/nested-where.f90 +++ b/flang/test/Lower/nested-where.f90 @@ -1,6 +1,6 @@ ! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s -! CHECK-LABEL: func @_QQmain() attributes {fir.bindc_name = "nested_where"} { +! CHECK-LABEL: func @_QQmain() attributes {fir.bindc_name = "NESTED_WHERE"} { program nested_where ! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {adapt.valuebyref, bindc_name = "i"} diff --git a/flang/test/Lower/polymorphic.f90 b/flang/test/Lower/polymorphic.f90 index b7be5f685d9e3..f586380e653a0 100644 --- a/flang/test/Lower/polymorphic.f90 +++ b/flang/test/Lower/polymorphic.f90 @@ -178,6 +178,17 @@ subroutine polymorphic_to_nonpolymorphic(p) ! CHECK-LABEL: func.func @_QMpolymorphic_testPpolymorphic_to_nonpolymorphic ! Just checking that FIR is generated without error. + subroutine nonpolymorphic_to_polymorphic(p, t) + type p1 + end type + type(p1), pointer :: p(:) + class(p1), target :: t(:) + p(0:1) => t + end subroutine + +! CHECK-LABEL: func.func @_QMpolymorphic_testPnonpolymorphic_to_polymorphic +! CHECK: fir.call @_FortranAPointerAssociateRemappingMonomorphic + ! Test that lowering does not crash for function return with unlimited ! polymoprhic value. @@ -1146,7 +1157,7 @@ program test l = i < o%inner end program -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "test"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "TEST"} { ! CHECK: %[[ADDR_O:.*]] = fir.address_of(@_QFEo) : !fir.ref}>>>> ! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[ADDR_O]] : (!fir.ref}>>>>) -> !fir.ref> ! CHECK: %{{.*}} = fir.call @_FortranAAllocatableAllocate(%[[BOX_NONE]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref>, !fir.ref, i1, !fir.box, !fir.ref, i32) -> i32 diff --git a/flang/test/Lower/pre-fir-tree02.f90 b/flang/test/Lower/pre-fir-tree02.f90 index f4fa626ba6548..65c33e9b364fe 100644 --- a/flang/test/Lower/pre-fir-tree02.f90 +++ b/flang/test/Lower/pre-fir-tree02.f90 @@ -3,7 +3,7 @@ ! Test Pre-FIR Tree captures all the intended nodes from the parse-tree ! Coarray and OpenMP related nodes are tested in other files. -! CHECK: Program test_prog +! CHECK: Program TEST_PROG program test_prog ! Check specification part is not part of the tree. interface diff --git a/flang/test/Lower/pre-fir-tree03.f90 b/flang/test/Lower/pre-fir-tree03.f90 index 313dab4d6ec7c..1de66e3f8d016 100644 --- a/flang/test/Lower/pre-fir-tree03.f90 +++ b/flang/test/Lower/pre-fir-tree03.f90 @@ -2,7 +2,7 @@ ! Test Pre-FIR Tree captures OpenMP related constructs -! CHECK: Program test_omp +! CHECK: Program TEST_OMP program test_omp ! CHECK: PrintStmt print *, "sequential" diff --git a/flang/test/Lower/pre-fir-tree06.f90 b/flang/test/Lower/pre-fir-tree06.f90 index f84bcd8b58b2d..ed1e76cb375bd 100644 --- a/flang/test/Lower/pre-fir-tree06.f90 +++ b/flang/test/Lower/pre-fir-tree06.f90 @@ -25,13 +25,13 @@ subroutine sub2() end ! CHECK: End Module m2 -! CHECK: Program main +! CHECK: Program MAIN program main real :: y ! CHECK-NEXT: OpenMPDeclarativeConstruct !$omp threadprivate(y) end -! CHECK: End Program main +! CHECK: End Program MAIN ! CHECK: Subroutine sub1 subroutine sub1() diff --git a/flang/test/Lower/program-units-fir-mangling.f90 b/flang/test/Lower/program-units-fir-mangling.f90 index e0af6f065f34d..65940b4e1ff17 100644 --- a/flang/test/Lower/program-units-fir-mangling.f90 +++ b/flang/test/Lower/program-units-fir-mangling.f90 @@ -124,7 +124,7 @@ subroutine should_not_collide() ! CHECK: } end subroutine -! CHECK-LABEL: func @_QQmain() attributes {fir.bindc_name = "test"} { +! CHECK-LABEL: func @_QQmain() attributes {fir.bindc_name = "TEST"} { program test ! CHECK: } contains diff --git a/flang/test/Lower/return-statement.f90 b/flang/test/Lower/return-statement.f90 index 6351a6859eb4f..8ab69e3146e2f 100644 --- a/flang/test/Lower/return-statement.f90 +++ b/flang/test/Lower/return-statement.f90 @@ -4,7 +4,7 @@ program basic return end program -! CHECK-LABEL: func @_QQmain() attributes {fir.bindc_name = "basic"} { +! CHECK-LABEL: func @_QQmain() attributes {fir.bindc_name = "BASIC"} { ! CHECK: return ! CHECK: } diff --git a/flang/test/Lower/volatile-openmp.f90 b/flang/test/Lower/volatile-openmp.f90 index 2e05b652822b5..d1a844eddd106 100644 --- a/flang/test/Lower/volatile-openmp.f90 +++ b/flang/test/Lower/volatile-openmp.f90 @@ -23,11 +23,11 @@ ! CHECK: %[[VAL_11:.*]] = fir.address_of(@_QFEcontainer) : !fir.ref>>}>> ! CHECK: %[[VAL_12:.*]] = fir.volatile_cast %[[VAL_11]] : (!fir.ref>>}>>) -> !fir.ref>>}>, volatile> ! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_12]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEcontainer"} : (!fir.ref>>}>, volatile>) -> (!fir.ref>>}>, volatile>, !fir.ref>>}>, volatile>) -! CHECK: %[[VAL_14:.*]] = fir.address_of(@_QFE.c.t) : !fir.ref>>,genre:i8,category:i8,kind:i8,rank:i8,__padding0:!fir.array<4xi8>,offset:i64,characterlen:!fir.type<_QM__fortran_type_infoTvalue{{[<]?}}{genre:i8,__padding0:!fir.array<7xi8>,value:i64}{{[>]?}}>,derived:!fir.box,name:!fir.box>>}>>>>,name:!fir.box>>,sizeinbytes:i64,uninstantiated:!fir.box>>,kindparameter:!fir.box>>,lenparameterkind:!fir.box>>,component:!fir.box>>>,procptr:!fir.box>>,offset:i64,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,special:!fir.box,proc:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}{{[>]?}}>>>>,specialbitset:i32,hasparent:i8,noinitializationneeded:i8,nodestructionneeded:i8,nofinalizationneeded:i8,nodefinedassignment:i8,__padding0:!fir.array<3xi8>}>>>,lenvalue:!fir.box,value:i64}{{[>]?}}>>>>,bounds:!fir.box,value:i64}{{[>]?}}>>>>,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>> +! CHECK: %[[VAL_14:.*]] = fir.address_of(@_QFE.c.t) : !fir.ref>>,genre:i8,category:i8,kind:i8,rank:i8,__padding0:!fir.array<4xi8>,offset:i64,characterlen:!fir.type<_QM__fortran_type_infoTvalue{{[<]?}}{genre:i8,__padding0:!fir.array<7xi8>,value:i64}{{[>]?}}>,derived:!fir.box,name:!fir.box>>}>>>>,name:!fir.box>>,sizeinbytes:i64,uninstantiated:!fir.box>>,kindparameter:!fir.box>>,lenparameterkind:!fir.box>>,component:!fir.box>>>,procptr:!fir.box>>,offset:i64,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,special:!fir.box,proc:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}{{[>]?}}>>>>,specialbitset:i32,hasparent:i8,noinitializationneeded:i8,nodestructionneeded:i8,nofinalizationneeded:i8,nodefinedassignment:i8,__padding0:!fir.array<3xi8>}>>>,lenvalue:!fir.box,value:i64}{{[>]?}}>>>>,bounds:!fir.box,value:i64}{{[>]?}}>>>>,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>> ! CHECK: %[[VAL_15:.*]] = fir.shape_shift %[[VAL_0]], %[[VAL_1]] : (index, index) -> !fir.shapeshift<1> -! CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %[[VAL_14]](%[[VAL_15]]) {fortran_attrs = #fir.var_attrs, uniq_name = "_QFE.c.t"} : (!fir.ref>>,genre:i8,category:i8,kind:i8,rank:i8,__padding0:!fir.array<4xi8>,offset:i64,characterlen:!fir.type<_QM__fortran_type_infoTvalue{{[<]?}}{genre:i8,__padding0:!fir.array<7xi8>,value:i64}{{[>]?}}>,derived:!fir.box,name:!fir.box>>}>>>>,name:!fir.box>>,sizeinbytes:i64,uninstantiated:!fir.box>>,kindparameter:!fir.box>>,lenparameterkind:!fir.box>>,component:!fir.box>>>,procptr:!fir.box>>,offset:i64,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,special:!fir.box,proc:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}{{[>]?}}>>>>,specialbitset:i32,hasparent:i8,noinitializationneeded:i8,nodestructionneeded:i8,nofinalizationneeded:i8,nodefinedassignment:i8,__padding0:!fir.array<3xi8>}>>>,lenvalue:!fir.box,value:i64}{{[>]?}}>>>>,bounds:!fir.box,value:i64}{{[>]?}}>>>>,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>>, !fir.shapeshift<1>) -> (!fir.box>>,genre:i8,category:i8,kind:i8,rank:i8,__padding0:!fir.array<4xi8>,offset:i64,characterlen:!fir.type<_QM__fortran_type_infoTvalue{{[<]?}}{genre:i8,__padding0:!fir.array<7xi8>,value:i64}{{[>]?}}>,derived:!fir.box,name:!fir.box>>}>>>>,name:!fir.box>>,sizeinbytes:i64,uninstantiated:!fir.box>>,kindparameter:!fir.box>>,lenparameterkind:!fir.box>>,component:!fir.box>>>,procptr:!fir.box>>,offset:i64,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,special:!fir.box,proc:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}{{[>]?}}>>>>,specialbitset:i32,hasparent:i8,noinitializationneeded:i8,nodestructionneeded:i8,nofinalizationneeded:i8,nodefinedassignment:i8,__padding0:!fir.array<3xi8>}>>>,lenvalue:!fir.box,value:i64}{{[>]?}}>>>>,bounds:!fir.box,value:i64}{{[>]?}}>>>>,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>>, !fir.ref>>,genre:i8,category:i8,kind:i8,rank:i8,__padding0:!fir.array<4xi8>,offset:i64,characterlen:!fir.type<_QM__fortran_type_infoTvalue{{[<]?}}{genre:i8,__padding0:!fir.array<7xi8>,value:i64}{{[>]?}}>,derived:!fir.box,name:!fir.box>>}>>>>,name:!fir.box>>,sizeinbytes:i64,uninstantiated:!fir.box>>,kindparameter:!fir.box>>,lenparameterkind:!fir.box>>,component:!fir.box>>>,procptr:!fir.box>>,offset:i64,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,special:!fir.box,proc:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}{{[>]?}}>>>>,specialbitset:i32,hasparent:i8,noinitializationneeded:i8,nodestructionneeded:i8,nofinalizationneeded:i8,nodefinedassignment:i8,__padding0:!fir.array<3xi8>}>>>,lenvalue:!fir.box,value:i64}{{[>]?}}>>>>,bounds:!fir.box,value:i64}{{[>]?}}>>>>,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>>) -! CHECK: %[[VAL_17:.*]] = fir.address_of(@_QFE.dt.t) : !fir.ref,name:!fir.box>>}>>>>,name:!fir.box>>,sizeinbytes:i64,uninstantiated:!fir.box>>,kindparameter:!fir.box>>,lenparameterkind:!fir.box>>,component:!fir.box>>,genre:i8,category:i8,kind:i8,rank:i8,__padding0:!fir.array<4xi8>,offset:i64,characterlen:!fir.type<_QM__fortran_type_infoTvalue{{[<]?}}{genre:i8,__padding0:!fir.array<7xi8>,value:i64}{{[>]?}}>,derived:!fir.box>>,lenvalue:!fir.box,value:i64}{{[>]?}}>>>>,bounds:!fir.box,value:i64}{{[>]?}}>>>>,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>>>,procptr:!fir.box>>,offset:i64,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,special:!fir.box,proc:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}{{[>]?}}>>>>,specialbitset:i32,hasparent:i8,noinitializationneeded:i8,nodestructionneeded:i8,nofinalizationneeded:i8,nodefinedassignment:i8,__padding0:!fir.array<3xi8>}>> -! CHECK: %[[VAL_18:.*]]:2 = hlfir.declare %[[VAL_17]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFE.dt.t"} : (!fir.ref,name:!fir.box>>}>>>>,name:!fir.box>>,sizeinbytes:i64,uninstantiated:!fir.box>>,kindparameter:!fir.box>>,lenparameterkind:!fir.box>>,component:!fir.box>>,genre:i8,category:i8,kind:i8,rank:i8,__padding0:!fir.array<4xi8>,offset:i64,characterlen:!fir.type<_QM__fortran_type_infoTvalue{{[<]?}}{genre:i8,__padding0:!fir.array<7xi8>,value:i64}{{[>]?}}>,derived:!fir.box>>,lenvalue:!fir.box,value:i64}{{[>]?}}>>>>,bounds:!fir.box,value:i64}{{[>]?}}>>>>,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>>>,procptr:!fir.box>>,offset:i64,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,special:!fir.box,proc:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}{{[>]?}}>>>>,specialbitset:i32,hasparent:i8,noinitializationneeded:i8,nodestructionneeded:i8,nofinalizationneeded:i8,nodefinedassignment:i8,__padding0:!fir.array<3xi8>}>>) -> (!fir.ref,name:!fir.box>>}>>>>,name:!fir.box>>,sizeinbytes:i64,uninstantiated:!fir.box>>,kindparameter:!fir.box>>,lenparameterkind:!fir.box>>,component:!fir.box>>,genre:i8,category:i8,kind:i8,rank:i8,__padding0:!fir.array<4xi8>,offset:i64,characterlen:!fir.type<_QM__fortran_type_infoTvalue{{[<]?}}{genre:i8,__padding0:!fir.array<7xi8>,value:i64}{{[>]?}}>,derived:!fir.box>>,lenvalue:!fir.box,value:i64}{{[>]?}}>>>>,bounds:!fir.box,value:i64}{{[>]?}}>>>>,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>>>,procptr:!fir.box>>,offset:i64,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,special:!fir.box,proc:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}{{[>]?}}>>>>,specialbitset:i32,hasparent:i8,noinitializationneeded:i8,nodestructionneeded:i8,nofinalizationneeded:i8,nodefinedassignment:i8,__padding0:!fir.array<3xi8>}>>, !fir.ref,name:!fir.box>>}>>>>,name:!fir.box>>,sizeinbytes:i64,uninstantiated:!fir.box>>,kindparameter:!fir.box>>,lenparameterkind:!fir.box>>,component:!fir.box>>,genre:i8,category:i8,kind:i8,rank:i8,__padding0:!fir.array<4xi8>,offset:i64,characterlen:!fir.type<_QM__fortran_type_infoTvalue{{[<]?}}{genre:i8,__padding0:!fir.array<7xi8>,value:i64}{{[>]?}}>,derived:!fir.box>>,lenvalue:!fir.box,value:i64}{{[>]?}}>>>>,bounds:!fir.box,value:i64}{{[>]?}}>>>>,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>>>,procptr:!fir.box>>,offset:i64,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,special:!fir.box,proc:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}{{[>]?}}>>>>,specialbitset:i32,hasparent:i8,noinitializationneeded:i8,nodestructionneeded:i8,nofinalizationneeded:i8,nodefinedassignment:i8,__padding0:!fir.array<3xi8>}>>) +! CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %[[VAL_14]](%[[VAL_15]]) {fortran_attrs = #fir.var_attrs, uniq_name = "_QFE.c.t"} : (!fir.ref>>,genre:i8,category:i8,kind:i8,rank:i8,__padding0:!fir.array<4xi8>,offset:i64,characterlen:!fir.type<_QM__fortran_type_infoTvalue{{[<]?}}{genre:i8,__padding0:!fir.array<7xi8>,value:i64}{{[>]?}}>,derived:!fir.box,name:!fir.box>>}>>>>,name:!fir.box>>,sizeinbytes:i64,uninstantiated:!fir.box>>,kindparameter:!fir.box>>,lenparameterkind:!fir.box>>,component:!fir.box>>>,procptr:!fir.box>>,offset:i64,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,special:!fir.box,proc:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}{{[>]?}}>>>>,specialbitset:i32,hasparent:i8,noinitializationneeded:i8,nodestructionneeded:i8,nofinalizationneeded:i8,nodefinedassignment:i8,__padding0:!fir.array<3xi8>}>>>,lenvalue:!fir.box,value:i64}{{[>]?}}>>>>,bounds:!fir.box,value:i64}{{[>]?}}>>>>,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>>, !fir.shapeshift<1>) -> (!fir.box>>,genre:i8,category:i8,kind:i8,rank:i8,__padding0:!fir.array<4xi8>,offset:i64,characterlen:!fir.type<_QM__fortran_type_infoTvalue{{[<]?}}{genre:i8,__padding0:!fir.array<7xi8>,value:i64}{{[>]?}}>,derived:!fir.box,name:!fir.box>>}>>>>,name:!fir.box>>,sizeinbytes:i64,uninstantiated:!fir.box>>,kindparameter:!fir.box>>,lenparameterkind:!fir.box>>,component:!fir.box>>>,procptr:!fir.box>>,offset:i64,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,special:!fir.box,proc:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}{{[>]?}}>>>>,specialbitset:i32,hasparent:i8,noinitializationneeded:i8,nodestructionneeded:i8,nofinalizationneeded:i8,nodefinedassignment:i8,__padding0:!fir.array<3xi8>}>>>,lenvalue:!fir.box,value:i64}{{[>]?}}>>>>,bounds:!fir.box,value:i64}{{[>]?}}>>>>,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>>, !fir.ref>>,genre:i8,category:i8,kind:i8,rank:i8,__padding0:!fir.array<4xi8>,offset:i64,characterlen:!fir.type<_QM__fortran_type_infoTvalue{{[<]?}}{genre:i8,__padding0:!fir.array<7xi8>,value:i64}{{[>]?}}>,derived:!fir.box,name:!fir.box>>}>>>>,name:!fir.box>>,sizeinbytes:i64,uninstantiated:!fir.box>>,kindparameter:!fir.box>>,lenparameterkind:!fir.box>>,component:!fir.box>>>,procptr:!fir.box>>,offset:i64,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,special:!fir.box,proc:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}{{[>]?}}>>>>,specialbitset:i32,hasparent:i8,noinitializationneeded:i8,nodestructionneeded:i8,nofinalizationneeded:i8,nodefinedassignment:i8,__padding0:!fir.array<3xi8>}>>>,lenvalue:!fir.box,value:i64}{{[>]?}}>>>>,bounds:!fir.box,value:i64}{{[>]?}}>>>>,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>>) +! CHECK: %[[VAL_17:.*]] = fir.address_of(@_QFE.dt.t) : !fir.ref,name:!fir.box>>}>>>>,name:!fir.box>>,sizeinbytes:i64,uninstantiated:!fir.box>>,kindparameter:!fir.box>>,lenparameterkind:!fir.box>>,component:!fir.box>>,genre:i8,category:i8,kind:i8,rank:i8,__padding0:!fir.array<4xi8>,offset:i64,characterlen:!fir.type<_QM__fortran_type_infoTvalue{{[<]?}}{genre:i8,__padding0:!fir.array<7xi8>,value:i64}{{[>]?}}>,derived:!fir.box>>,lenvalue:!fir.box,value:i64}{{[>]?}}>>>>,bounds:!fir.box,value:i64}{{[>]?}}>>>>,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>>>,procptr:!fir.box>>,offset:i64,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,special:!fir.box,proc:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}{{[>]?}}>>>>,specialbitset:i32,hasparent:i8,noinitializationneeded:i8,nodestructionneeded:i8,nofinalizationneeded:i8,nodefinedassignment:i8,__padding0:!fir.array<3xi8>}>> +! CHECK: %[[VAL_18:.*]]:2 = hlfir.declare %[[VAL_17]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFE.dt.t"} : (!fir.ref,name:!fir.box>>}>>>>,name:!fir.box>>,sizeinbytes:i64,uninstantiated:!fir.box>>,kindparameter:!fir.box>>,lenparameterkind:!fir.box>>,component:!fir.box>>,genre:i8,category:i8,kind:i8,rank:i8,__padding0:!fir.array<4xi8>,offset:i64,characterlen:!fir.type<_QM__fortran_type_infoTvalue{{[<]?}}{genre:i8,__padding0:!fir.array<7xi8>,value:i64}{{[>]?}}>,derived:!fir.box>>,lenvalue:!fir.box,value:i64}{{[>]?}}>>>>,bounds:!fir.box,value:i64}{{[>]?}}>>>>,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>>>,procptr:!fir.box>>,offset:i64,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,special:!fir.box,proc:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}{{[>]?}}>>>>,specialbitset:i32,hasparent:i8,noinitializationneeded:i8,nodestructionneeded:i8,nofinalizationneeded:i8,nodefinedassignment:i8,__padding0:!fir.array<3xi8>}>>) -> (!fir.ref,name:!fir.box>>}>>>>,name:!fir.box>>,sizeinbytes:i64,uninstantiated:!fir.box>>,kindparameter:!fir.box>>,lenparameterkind:!fir.box>>,component:!fir.box>>,genre:i8,category:i8,kind:i8,rank:i8,__padding0:!fir.array<4xi8>,offset:i64,characterlen:!fir.type<_QM__fortran_type_infoTvalue{{[<]?}}{genre:i8,__padding0:!fir.array<7xi8>,value:i64}{{[>]?}}>,derived:!fir.box>>,lenvalue:!fir.box,value:i64}{{[>]?}}>>>>,bounds:!fir.box,value:i64}{{[>]?}}>>>>,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>>>,procptr:!fir.box>>,offset:i64,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,special:!fir.box,proc:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}{{[>]?}}>>>>,specialbitset:i32,hasparent:i8,noinitializationneeded:i8,nodestructionneeded:i8,nofinalizationneeded:i8,nodefinedassignment:i8,__padding0:!fir.array<3xi8>}>>, !fir.ref,name:!fir.box>>}>>>>,name:!fir.box>>,sizeinbytes:i64,uninstantiated:!fir.box>>,kindparameter:!fir.box>>,lenparameterkind:!fir.box>>,component:!fir.box>>,genre:i8,category:i8,kind:i8,rank:i8,__padding0:!fir.array<4xi8>,offset:i64,characterlen:!fir.type<_QM__fortran_type_infoTvalue{{[<]?}}{genre:i8,__padding0:!fir.array<7xi8>,value:i64}{{[>]?}}>,derived:!fir.box>>,lenvalue:!fir.box,value:i64}{{[>]?}}>>>>,bounds:!fir.box,value:i64}{{[>]?}}>>>>,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}>>>>,procptr:!fir.box>>,offset:i64,initialization:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}>>>>,special:!fir.box,proc:!fir.type<_QM__fortran_builtinsT__builtin_c_funptr{__address:i64}>}{{[>]?}}>>>>,specialbitset:i32,hasparent:i8,noinitializationneeded:i8,nodestructionneeded:i8,nofinalizationneeded:i8,nodefinedassignment:i8,__padding0:!fir.array<3xi8>}>>) ! CHECK: %[[VAL_19:.*]] = hlfir.designate %[[VAL_13]]#0{"array"} {fortran_attrs = #fir.var_attrs} : (!fir.ref>>}>, volatile>) -> !fir.ref>>, volatile> ! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_19]] : !fir.ref>>, volatile> ! CHECK: %[[VAL_21:.*]]:3 = fir.box_dims %[[VAL_20]], %[[VAL_0]] : (!fir.box>>, index) -> (index, index, index) diff --git a/flang/test/Lower/volatile-openmp1.f90 b/flang/test/Lower/volatile-openmp1.f90 index 163db953b6b80..07d81a1aeb240 100644 --- a/flang/test/Lower/volatile-openmp1.f90 +++ b/flang/test/Lower/volatile-openmp1.f90 @@ -13,7 +13,7 @@ program main !$omp end parallel end program -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "main"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "MAIN"} { ! CHECK: %[[VAL_0:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_1:.*]] = arith.constant 1000 : i32 ! CHECK: %[[VAL_2:.*]] = arith.constant 0 : i32 diff --git a/flang/test/Lower/volatile-string.f90 b/flang/test/Lower/volatile-string.f90 index 88b21d7b245e9..f263db7abb5fc 100644 --- a/flang/test/Lower/volatile-string.f90 +++ b/flang/test/Lower/volatile-string.f90 @@ -21,7 +21,7 @@ subroutine assign_different_length(string) end subroutine end program -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "p"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "P"} { ! CHECK: %[[VAL_0:.*]] = arith.constant 11 : i32 ! CHECK: %[[VAL_1:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_2:.*]] = arith.constant true diff --git a/flang/test/Lower/volatile3.f90 b/flang/test/Lower/volatile3.f90 index 8825f8f3afbcb..a32f29d2bb9e7 100644 --- a/flang/test/Lower/volatile3.f90 +++ b/flang/test/Lower/volatile3.f90 @@ -70,7 +70,7 @@ subroutine sub_select_rank(arr) end program -! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "p"} { +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "P"} { ! CHECK: %[[VAL_0:.*]] = arith.constant 1 : index ! CHECK: %[[VAL_1:.*]] = arith.constant 0 : index ! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index diff --git a/flang/test/Parser/OpenMP/map-modifiers-v60.f90 b/flang/test/Parser/OpenMP/map-modifiers-v60.f90 new file mode 100644 index 0000000000000..bc80886780d46 --- /dev/null +++ b/flang/test/Parser/OpenMP/map-modifiers-v60.f90 @@ -0,0 +1,113 @@ +!RUN: %flang_fc1 -fdebug-unparse-no-sema -fopenmp -fopenmp-version=60 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +!RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema -fopenmp -fopenmp-version=60 %s | FileCheck --check-prefix="PARSE-TREE" %s + +subroutine f00(x) + integer :: x + !$omp target map(always, close, delete, present, ompx_hold: x) + x = x + 1 + !$omp end target +end + +!UNPARSE: SUBROUTINE f00 (x) +!UNPARSE: INTEGER x +!UNPARSE: !$OMP TARGET MAP(ALWAYS, CLOSE, DELETE, PRESENT, OMPX_HOLD: x) +!UNPARSE: x = x+1 +!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: | | Modifier -> OmpAlwaysModifier -> Value = Always +!PARSE-TREE: | | Modifier -> OmpCloseModifier -> Value = Close +!PARSE-TREE: | | Modifier -> OmpDeleteModifier -> Value = Delete +!PARSE-TREE: | | Modifier -> OmpPresentModifier -> Value = Present +!PARSE-TREE: | | Modifier -> OmpxHoldModifier -> Value = Ompx_Hold +!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' +!PARSE-TREE: | | bool = 'true' + +subroutine f01(x) + integer :: x + !$omp target map(self, storage: x) + x = x + 1 + !$omp end target +end + +!UNPARSE: !$OMP TARGET MAP(SELF, STORAGE: x) +!UNPARSE: x = x+1 +!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: | | Modifier -> OmpSelfModifier -> Value = Self +!PARSE-TREE: | | Modifier -> OmpMapType -> Value = Storage +!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' +!PARSE-TREE: | | bool = 'true' + +subroutine f02(x) + integer, pointer :: x + !$omp target map(ref_ptr, to: x) + x = x + 1 + !$omp end target +end + +!UNPARSE: SUBROUTINE f02 (x) +!UNPARSE: INTEGER, POINTER :: x +!UNPARSE: !$OMP TARGET MAP(REF_PTR, TO: x) +!UNPARSE: x = x+1 +!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: | | Modifier -> OmpRefModifier -> Value = Ref_Ptr +!PARSE-TREE: | | Modifier -> OmpMapType -> Value = To +!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' +!PARSE-TREE: | | bool = 'true' + +subroutine f03(x) + integer, pointer :: x + !$omp target map(ref_ptee, to: x) + x = x + 1 + !$omp end target +end + +!UNPARSE: SUBROUTINE f03 (x) +!UNPARSE: INTEGER, POINTER :: x +!UNPARSE: !$OMP TARGET MAP(REF_PTEE, TO: x) +!UNPARSE: x = x+1 +!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: | | Modifier -> OmpRefModifier -> Value = Ref_Ptee +!PARSE-TREE: | | Modifier -> OmpMapType -> Value = To +!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' +!PARSE-TREE: | | bool = 'true' + +subroutine f04(x) + integer, pointer :: x + !$omp target map(ref_ptr_ptee, to: x) + x = x + 1 + !$omp end target +end + +!UNPARSE: SUBROUTINE f04 (x) +!UNPARSE: INTEGER, POINTER :: x +!UNPARSE: !$OMP TARGET MAP(REF_PTR_PTEE, TO: x) +!UNPARSE: x = x+1 +!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: | | Modifier -> OmpRefModifier -> Value = Ref_Ptr_Ptee +!PARSE-TREE: | | Modifier -> OmpMapType -> Value = To +!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' +!PARSE-TREE: | | bool = 'true' diff --git a/flang/test/Parser/OpenMP/unroll-heuristic.f90 b/flang/test/Parser/OpenMP/unroll-heuristic.f90 new file mode 100644 index 0000000000000..2f589af0c83ca --- /dev/null +++ b/flang/test/Parser/OpenMP/unroll-heuristic.f90 @@ -0,0 +1,43 @@ +! RUN: %flang_fc1 -fopenmp -fopenmp-version=51 %s -fdebug-unparse | FileCheck --check-prefix=UNPARSE %s +! RUN: %flang_fc1 -fopenmp -fopenmp-version=51 %s -fdebug-dump-parse-tree | FileCheck --check-prefix=PTREE %s + +subroutine openmp_parse_unroll_heuristic + integer i + + !$omp unroll + do i = 1, 100 + call func(i) + end do + !$omp end unroll +END subroutine openmp_parse_unroll_heuristic + + +!UNPARSE: !$OMP UNROLL +!UNPARSE-NEXT: DO i=1_4,100_4 +!UNPARSE-NEXT: CALL func(i) +!UNPARSE-NEXT: END DO +!UNPARSE-NEXT: !$OMP END UNROLL + +!PTREE: OpenMPConstruct -> OpenMPLoopConstruct +!PTREE-NEXT: | OmpBeginLoopDirective +!PTREE-NEXT: | | OmpLoopDirective -> llvm::omp::Directive = unroll +!PTREE-NEXT: | | OmpClauseList -> +!PTREE-NEXT: | DoConstruct +!PTREE-NEXT: | | NonLabelDoStmt +!PTREE-NEXT: | | | LoopControl -> LoopBounds +!PTREE-NEXT: | | | | Scalar -> Name = 'i' +!PTREE-NEXT: | | | | Scalar -> Expr = '1_4' +!PTREE-NEXT: | | | | | LiteralConstant -> IntLiteralConstant = '1' +!PTREE-NEXT: | | | | Scalar -> Expr = '100_4' +!PTREE-NEXT: | | | | | LiteralConstant -> IntLiteralConstant = '100' +!PTREE-NEXT: | | Block +!PTREE-NEXT: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL func(i)' +!PTREE-NEXT: | | | | | | Call +!PTREE-NEXT: | | | | | ProcedureDesignator -> Name = 'func' +!PTREE-NEXT: | | | | | ActualArgSpec +!PTREE-NEXT: | | | | | | ActualArg -> Expr = 'i' +!PTREE-NEXT: | | | | | | | Designator -> DataRef -> Name = 'i' +!PTREE-NEXT: | | EndDoStmt -> +!PTREE-NEXT: | OmpEndLoopDirective +!PTREE-NEXT: | | OmpLoopDirective -> llvm::omp::Directive = unroll +!PTREE-NEXT: | | OmpClauseList -> diff --git a/flang/test/Parser/OpenMP/unroll.f90 b/flang/test/Parser/OpenMP/unroll-partial.f90 similarity index 100% rename from flang/test/Parser/OpenMP/unroll.f90 rename to flang/test/Parser/OpenMP/unroll-partial.f90 diff --git a/flang/test/Parser/acc-unparse.f90 b/flang/test/Parser/acc-unparse.f90 index 62e0d4487f3f7..12e6dec19f272 100644 --- a/flang/test/Parser/acc-unparse.f90 +++ b/flang/test/Parser/acc-unparse.f90 @@ -15,7 +15,7 @@ program bug47659 end do label1 end program -!CHECK-LABEL: PROGRAM bug47659 +!CHECK-LABEL: PROGRAM BUG47659 !CHECK: !$ACC PARALLEL LOOP diff --git a/flang/test/Semantics/OpenACC/acc-kernels-loop.f90 b/flang/test/Semantics/OpenACC/acc-kernels-loop.f90 index 29985a02eb6ef..cfe27e4f8fca1 100644 --- a/flang/test/Semantics/OpenACC/acc-kernels-loop.f90 +++ b/flang/test/Semantics/OpenACC/acc-kernels-loop.f90 @@ -243,8 +243,15 @@ program openacc_kernels_loop_validity a(i) = 3.14 end do + !$acc kernels loop default(none) private(N, a) + do i = 1, N + a(i) = 3.14 + end do + !$acc kernels loop default(none) + !ERROR: The DEFAULT(NONE) clause requires that 'n' must be listed in a data-mapping clause do i = 1, N + !ERROR: The DEFAULT(NONE) clause requires that 'a' must be listed in a data-mapping clause a(i) = 3.14 end do diff --git a/flang/test/Semantics/OpenACC/acc-symbols01.f90 b/flang/test/Semantics/OpenACC/acc-symbols01.f90 index 375445bad13a5..51a7a3a23e8ce 100644 --- a/flang/test/Semantics/OpenACC/acc-symbols01.f90 +++ b/flang/test/Semantics/OpenACC/acc-symbols01.f90 @@ -1,24 +1,24 @@ ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenacc -!DEF: /mm MainProgram -program mm - !DEF: /mm/x ObjectEntity REAL(4) - !DEF: /mm/y ObjectEntity REAL(4) +!DEF: /MM MainProgram +program MM + !DEF: /MM/x ObjectEntity REAL(4) + !DEF: /MM/y ObjectEntity REAL(4) real x, y - !DEF: /mm/a ObjectEntity INTEGER(4) - !DEF: /mm/b ObjectEntity INTEGER(4) - !DEF: /mm/c ObjectEntity INTEGER(4) - !DEF: /mm/i ObjectEntity INTEGER(4) + !DEF: /MM/a ObjectEntity INTEGER(4) + !DEF: /MM/b ObjectEntity INTEGER(4) + !DEF: /MM/c ObjectEntity INTEGER(4) + !DEF: /MM/i ObjectEntity INTEGER(4) integer a(10), b(10), c(10), i - !REF: /mm/b + !REF: /MM/b b = 2 !$acc parallel present(c) firstprivate(b) private(a) !$acc loop - !REF: /mm/i + !REF: /MM/i do i=1,10 - !REF: /mm/a - !REF: /mm/i - !REF: /mm/b + !REF: /MM/a + !REF: /MM/i + !REF: /MM/b a(i) = b(i) end do !$acc end parallel diff --git a/flang/test/Semantics/OpenMP/combined-constructs.f90 b/flang/test/Semantics/OpenMP/combined-constructs.f90 index 4f2a4a4f501b9..2298d33ef33eb 100644 --- a/flang/test/Semantics/OpenMP/combined-constructs.f90 +++ b/flang/test/Semantics/OpenMP/combined-constructs.f90 @@ -207,7 +207,7 @@ program main enddo !$omp end target teams - !ERROR: Only the TO, FROM, TOFROM, ALLOC map types are permitted for MAP clauses on the TARGET TEAMS directive + !ERROR: Only the ALLOC, FROM, TO, TOFROM map types are permitted for MAP clauses on the TARGET TEAMS directive !$omp target teams map(delete:a) do i = 1, N a(i) = 3.14 @@ -307,7 +307,7 @@ program main enddo !$omp end target teams distribute - !ERROR: Only the TO, FROM, TOFROM, ALLOC map types are permitted for MAP clauses on the TARGET TEAMS DISTRIBUTE directive + !ERROR: Only the ALLOC, FROM, TO, TOFROM map types are permitted for MAP clauses on the TARGET TEAMS DISTRIBUTE directive !$omp target teams distribute map(delete:a) do i = 1, N a(i) = 3.14 @@ -400,7 +400,7 @@ program main enddo !$omp end target teams distribute parallel do - !ERROR: Only the TO, FROM, TOFROM, ALLOC map types are permitted for MAP clauses on the TARGET TEAMS DISTRIBUTE PARALLEL DO directive + !ERROR: Only the ALLOC, FROM, TO, TOFROM map types are permitted for MAP clauses on the TARGET TEAMS DISTRIBUTE PARALLEL DO directive !$omp target teams distribute parallel do map(delete:a) do i = 1, N a(i) = 3.14 @@ -500,7 +500,7 @@ program main enddo !$omp end target teams distribute parallel do simd - !ERROR: Only the TO, FROM, TOFROM, ALLOC map types are permitted for MAP clauses on the TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD directive + !ERROR: Only the ALLOC, FROM, TO, TOFROM map types are permitted for MAP clauses on the TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD directive !$omp target teams distribute parallel do simd map(delete:a) do i = 1, N a(i) = 3.14 diff --git a/flang/test/Semantics/OpenMP/critical_within_default.f90 b/flang/test/Semantics/OpenMP/critical_within_default.f90 index dd972e6e52949..a5fe30eeb7de0 100644 --- a/flang/test/Semantics/OpenMP/critical_within_default.f90 +++ b/flang/test/Semantics/OpenMP/critical_within_default.f90 @@ -1,7 +1,7 @@ ! RUN: %flang_fc1 -fopenmp -fdebug-dump-symbols %s | FileCheck %s ! Test that we do not make a private copy of the critical name -!CHECK: MainProgram scope: mn +!CHECK: MainProgram scope: MN !CHECK-NEXT: j size=4 offset=0: ObjectEntity type: INTEGER(4) !CHECK-NEXT: OtherConstruct scope: !CHECK-NEXT: j (OmpPrivate): HostAssoc diff --git a/flang/test/Semantics/OpenMP/declare-mapper-symbols.f90 b/flang/test/Semantics/OpenMP/declare-mapper-symbols.f90 index 06f41ab8ce76f..e57a5c0c1cea6 100644 --- a/flang/test/Semantics/OpenMP/declare-mapper-symbols.f90 +++ b/flang/test/Semantics/OpenMP/declare-mapper-symbols.f90 @@ -1,7 +1,7 @@ ! RUN: %flang_fc1 -fdebug-dump-symbols -fopenmp -fopenmp-version=50 %s | FileCheck %s program main -!CHECK-LABEL: MainProgram scope: main +!CHECK-LABEL: MainProgram scope: MAIN implicit none type ty diff --git a/flang/test/Semantics/OpenMP/declare-reduction-mangled.f90 b/flang/test/Semantics/OpenMP/declare-reduction-mangled.f90 index 9d0a097fb1991..fc977f2f1b839 100644 --- a/flang/test/Semantics/OpenMP/declare-reduction-mangled.f90 +++ b/flang/test/Semantics/OpenMP/declare-reduction-mangled.f90 @@ -17,7 +17,7 @@ end function mymax end module mymod program omp_examples -!CHECK-LABEL: MainProgram scope: omp_examples +!CHECK-LABEL: MainProgram scope: OMP_EXAMPLES use mymod implicit none integer, parameter :: n = 100 diff --git a/flang/test/Semantics/OpenMP/declare-reduction-operators.f90 b/flang/test/Semantics/OpenMP/declare-reduction-operators.f90 index d7a9f2fc0a36b..84dbe1af01877 100644 --- a/flang/test/Semantics/OpenMP/declare-reduction-operators.f90 +++ b/flang/test/Semantics/OpenMP/declare-reduction-operators.f90 @@ -49,7 +49,7 @@ function my_add(x, y) end module m1 program test_vector -!CHECK-LABEL: MainProgram scope: test_vector +!CHECK-LABEL: MainProgram scope: TEST_VECTOR use vector_mod !CHECK: add_vectors (Function): Use from add_vectors in vector_mod implicit none diff --git a/flang/test/Semantics/OpenMP/declare-reduction-renamedop.f90 b/flang/test/Semantics/OpenMP/declare-reduction-renamedop.f90 index 12e80cbf7b327..9cd638d796091 100644 --- a/flang/test/Semantics/OpenMP/declare-reduction-renamedop.f90 +++ b/flang/test/Semantics/OpenMP/declare-reduction-renamedop.f90 @@ -22,7 +22,7 @@ end function my_mul end module module1 program test_omp_reduction -!CHECK: MainProgram scope: test_omp_reduction +!CHECK: MainProgram scope: TEST_OMP_REDUCTION use module1, only: t1, operator(.modmul.) => operator(.mul.) !CHECK: .modmul. (Function): Use from .mul. in module1 diff --git a/flang/test/Semantics/OpenMP/declare-reduction.f90 b/flang/test/Semantics/OpenMP/declare-reduction.f90 index ddca38fd57812..1f39c57c54ad1 100644 --- a/flang/test/Semantics/OpenMP/declare-reduction.f90 +++ b/flang/test/Semantics/OpenMP/declare-reduction.f90 @@ -31,7 +31,7 @@ end subroutine initme end function func program main -!CHECK-LABEL: MainProgram scope: main +!CHECK-LABEL: MainProgram scope: MAIN !$omp declare reduction (my_add_red : integer : omp_out = omp_out + omp_in) initializer (omp_priv=0) diff --git a/flang/test/Semantics/OpenMP/declare-target03.f90 b/flang/test/Semantics/OpenMP/declare-target03.f90 index 64a299d78224a..48cfc68393873 100644 --- a/flang/test/Semantics/OpenMP/declare-target03.f90 +++ b/flang/test/Semantics/OpenMP/declare-target03.f90 @@ -13,10 +13,10 @@ subroutine bar program main use mod1 - !ERROR: The module name or main program name cannot be in a DECLARE TARGET directive + !ERROR: The module name cannot be in a DECLARE TARGET directive !$omp declare target (mod1) - !PORTABILITY: Name 'main' declared in a main program should not have the same name as the main program [-Wbenign-name-clash] - !ERROR: The module name or main program name cannot be in a DECLARE TARGET directive + ! This is now allowed: "main" is implicitly declared symbol separate + ! from the main program symbol !$omp declare target (main) end diff --git a/flang/test/Semantics/OpenMP/device-constructs.f90 b/flang/test/Semantics/OpenMP/device-constructs.f90 index 6f545b9021966..431e0f88e3237 100644 --- a/flang/test/Semantics/OpenMP/device-constructs.f90 +++ b/flang/test/Semantics/OpenMP/device-constructs.f90 @@ -123,7 +123,7 @@ program main enddo !$omp end target - !ERROR: Only the TO, FROM, TOFROM, ALLOC map types are permitted for MAP clauses on the TARGET directive + !ERROR: Only the ALLOC, FROM, TO, TOFROM map types are permitted for MAP clauses on the TARGET directive !$omp target map(delete:a) do i = 1, N a = 3.14 @@ -160,7 +160,7 @@ program main !ERROR: At most one IF clause can appear on the TARGET ENTER DATA directive !$omp target enter data map(to:a) if(.true.) if(.false.) - !ERROR: Only the TO, ALLOC map types are permitted for MAP clauses on the TARGET ENTER DATA directive + !ERROR: Only the ALLOC, TO, TOFROM map types are permitted for MAP clauses on the TARGET ENTER DATA directive !$omp target enter data map(from:a) !$omp target exit data map(delete:a) @@ -168,7 +168,7 @@ program main !ERROR: At most one DEVICE clause can appear on the TARGET EXIT DATA directive !$omp target exit data map(from:a) device(0) device(1) - !ERROR: Only the FROM, RELEASE, DELETE map types are permitted for MAP clauses on the TARGET EXIT DATA directive + !ERROR: Only the DELETE, FROM, RELEASE, TOFROM map types are permitted for MAP clauses on the TARGET EXIT DATA directive !$omp target exit data map(to:a) !$omp target update if(.true.) device(1) to(a) from(b) depend(inout:c) nowait diff --git a/flang/test/Semantics/OpenMP/do-schedule03.f90 b/flang/test/Semantics/OpenMP/do-schedule03.f90 index 8787b094d581a..05602ca57e4a9 100644 --- a/flang/test/Semantics/OpenMP/do-schedule03.f90 +++ b/flang/test/Semantics/OpenMP/do-schedule03.f90 @@ -2,27 +2,27 @@ ! OpenMP Version 4.5 ! 2.7.1 Schedule Clause ! Test that does not catch non constant integer expressions like xx - xx. - !DEF: /ompdoschedule MainProgram -program ompdoschedule - !DEF: /ompdoschedule/a ObjectEntity REAL(4) - !DEF: /ompdoschedule/y ObjectEntity REAL(4) - !DEF: /ompdoschedule/z ObjectEntity REAL(4) + !DEF: /OMPDOSCHEDULE MainProgram +program OMPDOSCHEDULE + !DEF: /OMPDOSCHEDULE/a ObjectEntity REAL(4) + !DEF: /OMPDOSCHEDULE/y ObjectEntity REAL(4) + !DEF: /OMPDOSCHEDULE/z ObjectEntity REAL(4) real a(100),y(100),z(100) - !DEF: /ompdoschedule/b ObjectEntity INTEGER(4) - !DEF: /ompdoschedule/i ObjectEntity INTEGER(4) - !DEF: /ompdoschedule/n ObjectEntity INTEGER(4) + !DEF: /OMPDOSCHEDULE/b ObjectEntity INTEGER(4) + !DEF: /OMPDOSCHEDULE/i ObjectEntity INTEGER(4) + !DEF: /OMPDOSCHEDULE/n ObjectEntity INTEGER(4) integer b,i,n - !REF: /ompdoschedule/b + !REF: /OMPDOSCHEDULE/b b = 10 !$omp do schedule(static,b-b) - !DEF: /ompdoschedule/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) - !REF: /ompdoschedule/n + !DEF: /OMPDOSCHEDULE/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !REF: /OMPDOSCHEDULE/n do i = 2,n+1 - !REF: /ompdoschedule/y - !REF: /ompdoschedule/OtherConstruct1/i - !REF: /ompdoschedule/z - !REF: /ompdoschedule/a + !REF: /OMPDOSCHEDULE/y + !REF: /OMPDOSCHEDULE/OtherConstruct1/i + !REF: /OMPDOSCHEDULE/z + !REF: /OMPDOSCHEDULE/a y(i) = z(i-1) + a(i) end do !$omp end do -end program ompdoschedule +end program OMPDOSCHEDULE diff --git a/flang/test/Semantics/OpenMP/do01-positivecase.f90 b/flang/test/Semantics/OpenMP/do01-positivecase.f90 index 905fdbaf18476..50a6870f43896 100644 --- a/flang/test/Semantics/OpenMP/do01-positivecase.f90 +++ b/flang/test/Semantics/OpenMP/do01-positivecase.f90 @@ -4,16 +4,16 @@ ! The loop iteration variable may not appear in a firstprivate directive. ! A positive case -!DEF: /omp_do MainProgram -program omp_do - !DEF: /omp_do/i ObjectEntity INTEGER(4) +!DEF: /OMP_DO MainProgram +program OMP_DO + !DEF: /OMP_DO/i ObjectEntity INTEGER(4) integer i !$omp do firstprivate(k) - !DEF: /omp_do/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_DO/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 print *, "Hello" end do !$omp end do -end program omp_do +end program OMP_DO diff --git a/flang/test/Semantics/OpenMP/do04-positivecase.f90 b/flang/test/Semantics/OpenMP/do04-positivecase.f90 index eb2d67bb8ceb2..51b69fce3c7cc 100644 --- a/flang/test/Semantics/OpenMP/do04-positivecase.f90 +++ b/flang/test/Semantics/OpenMP/do04-positivecase.f90 @@ -2,21 +2,21 @@ ! OpenMP Version 4.5 ! 2.7.1 Do Loop Constructs -!DEF: /omp_do1 MainProgram -program omp_do1 - !DEF: /omp_do1/i ObjectEntity INTEGER(4) - !DEF: /omp_do1/j ObjectEntity INTEGER(4) - !DEF: /omp_do1/k (OmpThreadprivate) ObjectEntity INTEGER(4) - !DEF: /omp_do1/n (OmpThreadprivate) ObjectEntity INTEGER(4) +!DEF: /OMP_DO1 MainProgram +program OMP_DO1 + !DEF: /OMP_DO1/i ObjectEntity INTEGER(4) + !DEF: /OMP_DO1/j ObjectEntity INTEGER(4) + !DEF: /OMP_DO1/k (OmpThreadprivate) ObjectEntity INTEGER(4) + !DEF: /OMP_DO1/n (OmpThreadprivate) ObjectEntity INTEGER(4) integer i, j, k, n !$omp threadprivate (k,n) !$omp do - !DEF: /omp_do1/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_DO1/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !REF: /omp_do1/j + !REF: /OMP_DO1/j do j=1,10 print *, "Hello" end do end do !$omp end do -end program omp_do1 +end program OMP_DO1 diff --git a/flang/test/Semantics/OpenMP/do05-positivecase.f90 b/flang/test/Semantics/OpenMP/do05-positivecase.f90 index eda04610535c2..d4eb1fd6bc3da 100644 --- a/flang/test/Semantics/OpenMP/do05-positivecase.f90 +++ b/flang/test/Semantics/OpenMP/do05-positivecase.f90 @@ -3,13 +3,13 @@ ! 2.7.1 Loop Construct restrictions on single directive. ! A positive case -!DEF: /omp_do MainProgram -program omp_do - !DEF: /omp_do/i ObjectEntity INTEGER(4) - !DEF: /omp_do/n ObjectEntity INTEGER(4) +!DEF: /OMP_DO MainProgram +program OMP_DO + !DEF: /OMP_DO/i ObjectEntity INTEGER(4) + !DEF: /OMP_DO/n ObjectEntity INTEGER(4) integer i,n !$omp parallel - !DEF: /omp_do/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_DO/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 !$omp single print *, "hello" @@ -19,13 +19,13 @@ program omp_do !$omp parallel default(shared) !$omp do - !DEF: /omp_do/OtherConstruct2/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) - !DEF: /omp_do/OtherConstruct2/OtherConstruct1/n HostAssoc INTEGER(4) + !DEF: /OMP_DO/OtherConstruct2/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_DO/OtherConstruct2/OtherConstruct1/n HostAssoc INTEGER(4) do i=1,n !$omp parallel !$omp single !DEF: /work EXTERNAL (Subroutine) ProcEntity - !DEF: /omp_do/OtherConstruct2/OtherConstruct1/OtherConstruct1/OtherConstruct1/i HostAssoc INTEGER(4) + !DEF: /OMP_DO/OtherConstruct2/OtherConstruct1/OtherConstruct1/OtherConstruct1/i HostAssoc INTEGER(4) call work(i, 1) !$omp end single !$omp end parallel @@ -34,7 +34,7 @@ program omp_do !$omp end parallel !$omp parallel private(i) - !DEF: /omp_do/OtherConstruct3/i (OmpPrivate, OmpExplicit) HostAssoc INTEGER(4) + !DEF: /OMP_DO/OtherConstruct3/i (OmpPrivate, OmpExplicit) HostAssoc INTEGER(4) do i=1,10 !$omp single print *, "hello" @@ -43,32 +43,32 @@ program omp_do !$omp end parallel !$omp target teams distribute parallel do - !DEF:/omp_do/OtherConstruct4/i (OmpPrivate ,OmpPreDetermined) HostAssoc INTEGER(4) + !DEF:/OMP_DO/OtherConstruct4/i (OmpPrivate ,OmpPreDetermined) HostAssoc INTEGER(4) do i=1,100 - !REF:/omp_do/OtherConstruct4/i + !REF:/OMP_DO/OtherConstruct4/i if(i<10) cycle end do !$omp end target teams distribute parallel do !$omp target teams distribute parallel do simd - !DEF:/omp_do/OtherConstruct5/i (OmpLinear,OmpPreDetermined) HostAssoc INTEGER(4) + !DEF:/OMP_DO/OtherConstruct5/i (OmpLinear,OmpPreDetermined) HostAssoc INTEGER(4) do i=1,100 - !REF:/omp_do/OtherConstruct5/i + !REF:/OMP_DO/OtherConstruct5/i if(i<10) cycle end do !$omp end target teams distribute parallel do simd !$omp target teams distribute - !DEF: /omp_do/OtherConstruct6/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_DO/OtherConstruct6/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,100 - !REF: /omp_do/OtherConstruct6/i + !REF: /OMP_DO/OtherConstruct6/i if(i < 5) cycle end do !$omp target teams distribute simd - !DEF: /omp_do/OtherConstruct7/i (OmpLinear, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_DO/OtherConstruct7/i (OmpLinear, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,100 - !REF: /omp_do/OtherConstruct7/i + !REF: /OMP_DO/OtherConstruct7/i if(i < 5) cycle end do -end program omp_do +end program OMP_DO diff --git a/flang/test/Semantics/OpenMP/do06-positivecases.f90 b/flang/test/Semantics/OpenMP/do06-positivecases.f90 index 2713b55fa2ecb..dfb1d999bbc53 100644 --- a/flang/test/Semantics/OpenMP/do06-positivecases.f90 +++ b/flang/test/Semantics/OpenMP/do06-positivecases.f90 @@ -5,14 +5,14 @@ ! region ever binds to a loop region arising from the loop construct. ! A positive case -!DEF: /omp_do MainProgram -program omp_do - !DEF: /omp_do/i ObjectEntity INTEGER(4) - !DEF: /omp_do/j ObjectEntity INTEGER(4) - !DEF: /omp_do/k ObjectEntity INTEGER(4) +!DEF: /OMP_DO MainProgram +program OMP_DO + !DEF: /OMP_DO/i ObjectEntity INTEGER(4) + !DEF: /OMP_DO/j ObjectEntity INTEGER(4) + !DEF: /OMP_DO/k ObjectEntity INTEGER(4) integer i, j, k !$omp do ordered - !DEF: /omp_do/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_DO/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 !$omp ordered !DEF: /my_func EXTERNAL (Subroutine) ProcEntity @@ -20,4 +20,4 @@ program omp_do !$omp end ordered end do !$omp end do -end program omp_do +end program OMP_DO diff --git a/flang/test/Semantics/OpenMP/do11.f90 b/flang/test/Semantics/OpenMP/do11.f90 index faab457efff3c..472048d684276 100644 --- a/flang/test/Semantics/OpenMP/do11.f90 +++ b/flang/test/Semantics/OpenMP/do11.f90 @@ -2,24 +2,24 @@ ! OpenMP Version 4.5 ! 2.7.1 Do Loop Constructs -!DEF: /omp_do MainProgram -program omp_do - !DEF: /omp_do/i ObjectEntity INTEGER(4) - !DEF: /omp_do/j ObjectEntity INTEGER(4) - !DEF: /omp_do/k ObjectEntity INTEGER(4) +!DEF: /OMP_DO MainProgram +program OMP_DO + !DEF: /OMP_DO/i ObjectEntity INTEGER(4) + !DEF: /OMP_DO/j ObjectEntity INTEGER(4) + !DEF: /OMP_DO/k ObjectEntity INTEGER(4) integer i, j, k !$omp do - !DEF: /omp_do/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_DO/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !REF: /omp_do/j + !REF: /OMP_DO/j do j=1,10 - !REF: /omp_do/OtherConstruct1/i - !REF: /omp_do/j + !REF: /OMP_DO/OtherConstruct1/i + !REF: /OMP_DO/j print *, "it", i, j end do end do !$omp end do -end program omp_do +end program OMP_DO !DEF: /omp_do2 (Subroutine)Subprogram subroutine omp_do2 diff --git a/flang/test/Semantics/OpenMP/do12.f90 b/flang/test/Semantics/OpenMP/do12.f90 index a057a246f7a99..06055b7572a60 100644 --- a/flang/test/Semantics/OpenMP/do12.f90 +++ b/flang/test/Semantics/OpenMP/do12.f90 @@ -2,20 +2,20 @@ ! OpenMP Version 4.5 ! 2.7.1 Do Loop constructs. -!DEF: /omp_cycle MainProgram -program omp_cycle +!DEF: /OMP_CYCLE MainProgram +program OMP_CYCLE !$omp do collapse(1) - !DEF: /omp_cycle/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_CYCLE/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=0,10 - !REF: /omp_cycle/OtherConstruct1/i + !REF: /OMP_CYCLE/OtherConstruct1/i if (i<1) cycle - !DEF: /omp_cycle/j (Implicit) ObjectEntity INTEGER(4) + !DEF: /OMP_CYCLE/j (Implicit) ObjectEntity INTEGER(4) do j=0,10 - !DEF: /omp_cycle/k (Implicit) ObjectEntity INTEGER(4) + !DEF: /OMP_CYCLE/k (Implicit) ObjectEntity INTEGER(4) do k=0,10 - !REF: /omp_cycle/OtherConstruct1/i - !REF: /omp_cycle/j - !REF: /omp_cycle/k + !REF: /OMP_CYCLE/OtherConstruct1/i + !REF: /OMP_CYCLE/j + !REF: /OMP_CYCLE/k print *, i, j, k end do end do @@ -23,17 +23,17 @@ program omp_cycle !$omp end do !$omp do collapse(1) - !DEF: /omp_cycle/OtherConstruct2/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_CYCLE/OtherConstruct2/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=0,10 - !REF: /omp_cycle/j + !REF: /OMP_CYCLE/j do j=0,10 - !REF: /omp_cycle/OtherConstruct2/i + !REF: /OMP_CYCLE/OtherConstruct2/i if (i<1) cycle - !REF: /omp_cycle/k + !REF: /OMP_CYCLE/k do k=0,10 - !REF: /omp_cycle/OtherConstruct2/i - !REF: /omp_cycle/j - !REF: /omp_cycle/k + !REF: /OMP_CYCLE/OtherConstruct2/i + !REF: /OMP_CYCLE/j + !REF: /OMP_CYCLE/k print *, i, j, k end do end do @@ -41,17 +41,17 @@ program omp_cycle !$omp end do !$omp do collapse(2) - !DEF: /omp_cycle/OtherConstruct3/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_CYCLE/OtherConstruct3/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=0,10 - !DEF: /omp_cycle/OtherConstruct3/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_CYCLE/OtherConstruct3/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do j=0,10 - !REF: /omp_cycle/k + !REF: /OMP_CYCLE/k do k=0,10 - !REF: /omp_cycle/OtherConstruct3/i + !REF: /OMP_CYCLE/OtherConstruct3/i if (i<1) cycle - !REF: /omp_cycle/OtherConstruct3/i - !REF: /omp_cycle/OtherConstruct3/j - !REF: /omp_cycle/k + !REF: /OMP_CYCLE/OtherConstruct3/i + !REF: /OMP_CYCLE/OtherConstruct3/j + !REF: /OMP_CYCLE/k print *, i, j, k end do end do @@ -59,17 +59,17 @@ program omp_cycle !$omp end do !$omp do collapse(3) - !DEF: /omp_cycle/OtherConstruct4/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_CYCLE/OtherConstruct4/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=0,10 - !DEF: /omp_cycle/OtherConstruct4/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_CYCLE/OtherConstruct4/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do j=0,10 - !DEF: /omp_cycle/OtherConstruct4/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_CYCLE/OtherConstruct4/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do k=0,10 - !REF: /omp_cycle/OtherConstruct4/i + !REF: /OMP_CYCLE/OtherConstruct4/i if (i<1) cycle - !REF: /omp_cycle/OtherConstruct4/i - !REF: /omp_cycle/OtherConstruct4/j - !REF: /omp_cycle/OtherConstruct4/k + !REF: /OMP_CYCLE/OtherConstruct4/i + !REF: /OMP_CYCLE/OtherConstruct4/j + !REF: /OMP_CYCLE/OtherConstruct4/k print *, i, j, k end do end do @@ -77,20 +77,20 @@ program omp_cycle !$omp end do !$omp do collapse(3) - !DEF: /omp_cycle/OtherConstruct5/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_CYCLE/OtherConstruct5/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) foo:do i=0,10 - !DEF: /omp_cycle/OtherConstruct5/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_CYCLE/OtherConstruct5/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) foo1:do j=0,10 - !DEF: /omp_cycle/OtherConstruct5/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_CYCLE/OtherConstruct5/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) foo2:do k=0,10 - !REF: /omp_cycle/OtherConstruct5/i + !REF: /OMP_CYCLE/OtherConstruct5/i if (i<1) cycle foo2 - !REF: /omp_cycle/OtherConstruct5/i - !REF: /omp_cycle/OtherConstruct5/j - !REF: /omp_cycle/OtherConstruct5/k + !REF: /OMP_CYCLE/OtherConstruct5/i + !REF: /OMP_CYCLE/OtherConstruct5/j + !REF: /OMP_CYCLE/OtherConstruct5/k print *, i, j, k end do foo2 end do foo1 end do foo !$omp end do -end program omp_cycle +end program OMP_CYCLE diff --git a/flang/test/Semantics/OpenMP/do14.f90 b/flang/test/Semantics/OpenMP/do14.f90 index 5e8a5a64c2979..e17647394fff7 100644 --- a/flang/test/Semantics/OpenMP/do14.f90 +++ b/flang/test/Semantics/OpenMP/do14.f90 @@ -2,19 +2,19 @@ ! OpenMP Version 4.5 ! 2.7.1 Do Loop constructs. -!DEF: /omp_cycle MainProgram -program omp_cycle +!DEF: /OMP_CYCLE MainProgram +program OMP_CYCLE !$omp do collapse(1) - !DEF: /omp_cycle/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_CYCLE/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=0,10 cycle - !DEF: /omp_cycle/j (Implicit) ObjectEntity INTEGER(4) + !DEF: /OMP_CYCLE/j (Implicit) ObjectEntity INTEGER(4) do j=0,10 - !DEF: /omp_cycle/k (Implicit) ObjectEntity INTEGER(4) + !DEF: /OMP_CYCLE/k (Implicit) ObjectEntity INTEGER(4) do k=0,10 - !REF: /omp_cycle/OtherConstruct1/i - !REF: /omp_cycle/j - !REF: /omp_cycle/k + !REF: /OMP_CYCLE/OtherConstruct1/i + !REF: /OMP_CYCLE/j + !REF: /OMP_CYCLE/k print *, i, j, k end do end do @@ -22,16 +22,16 @@ program omp_cycle !$omp end do !$omp do collapse(1) - !DEF: /omp_cycle/OtherConstruct2/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_CYCLE/OtherConstruct2/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=0,10 - !REF: /omp_cycle/j + !REF: /OMP_CYCLE/j do j=0,10 cycle - !REF: /omp_cycle/k + !REF: /OMP_CYCLE/k do k=0,10 - !REF: /omp_cycle/OtherConstruct2/i - !REF: /omp_cycle/j - !REF: /omp_cycle/k + !REF: /OMP_CYCLE/OtherConstruct2/i + !REF: /OMP_CYCLE/j + !REF: /OMP_CYCLE/k print *, i, j, k end do end do @@ -39,16 +39,16 @@ program omp_cycle !$omp end do !$omp do collapse(2) - !DEF: /omp_cycle/OtherConstruct3/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_CYCLE/OtherConstruct3/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=0,10 - !DEF: /omp_cycle/OtherConstruct3/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_CYCLE/OtherConstruct3/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do j=0,10 - !REF: /omp_cycle/k + !REF: /OMP_CYCLE/k do k=0,10 cycle - !REF: /omp_cycle/OtherConstruct3/i - !REF: /omp_cycle/OtherConstruct3/j - !REF: /omp_cycle/k + !REF: /OMP_CYCLE/OtherConstruct3/i + !REF: /OMP_CYCLE/OtherConstruct3/j + !REF: /OMP_CYCLE/k print *, i, j, k end do end do @@ -56,16 +56,16 @@ program omp_cycle !$omp end do !$omp do collapse(3) - !DEF: /omp_cycle/OtherConstruct4/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_CYCLE/OtherConstruct4/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=0,10 - !DEF: /omp_cycle/OtherConstruct4/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_CYCLE/OtherConstruct4/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do j=0,10 - !DEF: /omp_cycle/OtherConstruct4/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_CYCLE/OtherConstruct4/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do k=0,10 cycle - !REF: /omp_cycle/OtherConstruct4/i - !REF: /omp_cycle/OtherConstruct4/j - !REF: /omp_cycle/OtherConstruct4/k + !REF: /OMP_CYCLE/OtherConstruct4/i + !REF: /OMP_CYCLE/OtherConstruct4/j + !REF: /OMP_CYCLE/OtherConstruct4/k print *, i, j, k end do end do @@ -73,19 +73,19 @@ program omp_cycle !$omp end do !$omp do ordered(3) - !DEF: /omp_cycle/OtherConstruct5/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_CYCLE/OtherConstruct5/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) foo:do i=0,10 - !DEF: /omp_cycle/OtherConstruct5/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_CYCLE/OtherConstruct5/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) foo1:do j=0,10 - !DEF: /omp_cycle/OtherConstruct5/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_CYCLE/OtherConstruct5/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) foo2:do k=0,10 cycle foo2 - !REF: /omp_cycle/OtherConstruct5/i - !REF: /omp_cycle/OtherConstruct5/j - !REF: /omp_cycle/OtherConstruct5/k + !REF: /OMP_CYCLE/OtherConstruct5/i + !REF: /OMP_CYCLE/OtherConstruct5/j + !REF: /OMP_CYCLE/OtherConstruct5/k print *, i, j, k end do foo2 end do foo1 end do foo !$omp end do -end program omp_cycle +end program OMP_CYCLE diff --git a/flang/test/Semantics/OpenMP/do17.f90 b/flang/test/Semantics/OpenMP/do17.f90 index c0c59f16dee1b..cac11f215f074 100644 --- a/flang/test/Semantics/OpenMP/do17.f90 +++ b/flang/test/Semantics/OpenMP/do17.f90 @@ -2,56 +2,56 @@ ! OpenMP Version 4.5 ! 2.7.1 Do Loop constructs. -!DEF: /test MainProgram -program test - !DEF: /test/i ObjectEntity INTEGER(4) - !DEF: /test/j ObjectEntity INTEGER(4) - !DEF: /test/k ObjectEntity INTEGER(4) +!DEF: /TEST MainProgram +program TEST + !DEF: /TEST/i ObjectEntity INTEGER(4) + !DEF: /TEST/j ObjectEntity INTEGER(4) + !DEF: /TEST/k ObjectEntity INTEGER(4) integer i, j, k !$omp do collapse(2) - !DEF: /test/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /TEST/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) foo: do i=0,10 - !DEF: /test/OtherConstruct1/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /TEST/OtherConstruct1/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) foo1: do j=0,10 - !REF: /test/k + !REF: /TEST/k foo2: do k=0,10 - !REF: /test/OtherConstruct1/i + !REF: /TEST/OtherConstruct1/i select case (i) case (5) cycle foo1 case (7) cycle foo2 end select - !REF: /test/OtherConstruct1/i - !REF: /test/OtherConstruct1/j - !REF: /test/k + !REF: /TEST/OtherConstruct1/i + !REF: /TEST/OtherConstruct1/j + !REF: /TEST/k print *, i, j, k end do foo2 end do foo1 end do foo !$omp do collapse(2) - !DEF: /test/OtherConstruct2/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /TEST/OtherConstruct2/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) foo: do i=0,10 - !DEF: /test/OtherConstruct2/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /TEST/OtherConstruct2/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) foo1: do j=0,10 - !REF: /test/k + !REF: /TEST/k foo2: do k=0,10 - !REF: /test/OtherConstruct2/i + !REF: /TEST/OtherConstruct2/i if (i<3) then cycle foo1 - !REF: /test/OtherConstruct2/i + !REF: /TEST/OtherConstruct2/i else if (i>8) then cycle foo1 else cycle foo2 end if - !REF: /test/OtherConstruct2/i - !REF: /test/OtherConstruct2/j - !REF: /test/k + !REF: /TEST/OtherConstruct2/i + !REF: /TEST/OtherConstruct2/j + !REF: /TEST/k print *, i, j, k end do foo2 end do foo1 end do foo !$omp end do -end program test +end program TEST diff --git a/flang/test/Semantics/OpenMP/map-clause-symbols.f90 b/flang/test/Semantics/OpenMP/map-clause-symbols.f90 index 8f984fcd2fa7e..1d6315b4a2312 100644 --- a/flang/test/Semantics/OpenMP/map-clause-symbols.f90 +++ b/flang/test/Semantics/OpenMP/map-clause-symbols.f90 @@ -1,6 +1,6 @@ ! RUN: %flang_fc1 -fdebug-dump-symbols -fopenmp -fopenmp-version=50 %s | FileCheck %s program main -!CHECK-LABEL: MainProgram scope: main +!CHECK-LABEL: MainProgram scope: MAIN integer, parameter :: n = 256 real(8) :: a(256) !$omp target map(mapper(xx), from:a) diff --git a/flang/test/Semantics/OpenMP/map-modifiers-v60.f90 b/flang/test/Semantics/OpenMP/map-modifiers-v60.f90 new file mode 100644 index 0000000000000..b3f2e5171d6d6 --- /dev/null +++ b/flang/test/Semantics/OpenMP/map-modifiers-v60.f90 @@ -0,0 +1,35 @@ +!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=52 -Werror + +subroutine f00(x) + integer :: x +!WARNING: 'self-modifier' modifier is not supported in OpenMP v5.2, try -fopenmp-version=60 + !$omp target map(self: x) + x = x + 1 + !$omp end target +end + +subroutine f01(x) + integer, pointer :: x +!WARNING: 'ref-modifier' modifier is not supported in OpenMP v5.2, try -fopenmp-version=60 + !$omp target map(ref_ptr: x) + x = x + 1 + !$omp end target +end + +subroutine f02(x) + integer, pointer :: x +!WARNING: 'ref-modifier' modifier is not supported in OpenMP v5.2, try -fopenmp-version=60 + !$omp target map(ref_ptee: x) + x = x + 1 + !$omp end target +end + +subroutine f03(x) + integer, pointer :: x +!WARNING: 'ref-modifier' modifier is not supported in OpenMP v5.2, try -fopenmp-version=60 + !$omp target map(ref_ptr_ptee: x) + x = x + 1 + !$omp end target +end + + diff --git a/flang/test/Semantics/OpenMP/reduction08.f90 b/flang/test/Semantics/OpenMP/reduction08.f90 index 01a06eb7d7414..b4a81e644c1e7 100644 --- a/flang/test/Semantics/OpenMP/reduction08.f90 +++ b/flang/test/Semantics/OpenMP/reduction08.f90 @@ -2,62 +2,62 @@ ! OpenMP Version 4.5 ! 2.15.3.6 Reduction Clause Positive cases -!DEF: /omp_reduction MainProgram -program omp_reduction - !DEF: /omp_reduction/i ObjectEntity INTEGER(4) +!DEF: /OMP_REDUCTION MainProgram +program OMP_REDUCTION + !DEF: /OMP_REDUCTION/i ObjectEntity INTEGER(4) integer i - !DEF: /omp_reduction/k ObjectEntity INTEGER(4) + !DEF: /OMP_REDUCTION/k ObjectEntity INTEGER(4) integer :: k = 10 - !DEF: /omp_reduction/m ObjectEntity INTEGER(4) + !DEF: /OMP_REDUCTION/m ObjectEntity INTEGER(4) integer :: m = 12 !$omp parallel do reduction(max:k) - !DEF: /omp_reduction/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct1/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) - !DEF: /omp_reduction/max ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity - !DEF: /omp_reduction/OtherConstruct1/m (OmpShared) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct1/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/max ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity + !DEF: /OMP_REDUCTION/OtherConstruct1/m (OmpShared) HostAssoc INTEGER(4) k = max(k, m) end do !$omp end parallel do !$omp parallel do reduction(min:k) - !DEF: /omp_reduction/OtherConstruct2/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct2/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct2/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) - !DEF: /omp_reduction/min ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity - !DEF: /omp_reduction/OtherConstruct2/m (OmpShared) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct2/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/min ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity + !DEF: /OMP_REDUCTION/OtherConstruct2/m (OmpShared) HostAssoc INTEGER(4) k = min(k, m) end do !$omp end parallel do !$omp parallel do reduction(iand:k) - !DEF: /omp_reduction/OtherConstruct3/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct3/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct3/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) - !DEF: /omp_reduction/iand ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity - !DEF: /omp_reduction/OtherConstruct3/m (OmpShared) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct3/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/iand ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity + !DEF: /OMP_REDUCTION/OtherConstruct3/m (OmpShared) HostAssoc INTEGER(4) k = iand(k, m) end do !$omp end parallel do !$omp parallel do reduction(ior:k) - !DEF: /omp_reduction/OtherConstruct4/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct4/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct4/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) - !DEF: /omp_reduction/ior ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity - !DEF: /omp_reduction/OtherConstruct4/m (OmpShared) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct4/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/ior ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity + !DEF: /OMP_REDUCTION/OtherConstruct4/m (OmpShared) HostAssoc INTEGER(4) k = ior(k, m) end do !$omp end parallel do !$omp parallel do reduction(ieor:k) - !DEF: /omp_reduction/OtherConstruct5/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct5/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct5/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) - !DEF: /omp_reduction/ieor ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity - !DEF: /omp_reduction/OtherConstruct5/m (OmpShared) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct5/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/ieor ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity + !DEF: /OMP_REDUCTION/OtherConstruct5/m (OmpShared) HostAssoc INTEGER(4) k = ieor(k,m) end do !$omp end parallel do -end program omp_reduction +end program OMP_REDUCTION diff --git a/flang/test/Semantics/OpenMP/reduction09.f90 b/flang/test/Semantics/OpenMP/reduction09.f90 index d6c71c30d2834..ca60805e8c416 100644 --- a/flang/test/Semantics/OpenMP/reduction09.f90 +++ b/flang/test/Semantics/OpenMP/reduction09.f90 @@ -1,22 +1,22 @@ ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.15.3.6 Reduction Clause Positive cases. -!DEF: /omp_reduction MainProgram -program omp_reduction - !DEF: /omp_reduction/i ObjectEntity INTEGER(4) +!DEF: /OMP_REDUCTION MainProgram +program OMP_REDUCTION + !DEF: /OMP_REDUCTION/i ObjectEntity INTEGER(4) integer i - !DEF: /omp_reduction/k ObjectEntity INTEGER(4) + !DEF: /OMP_REDUCTION/k ObjectEntity INTEGER(4) integer :: k = 10 - !DEF: /omp_reduction/a ObjectEntity INTEGER(4) + !DEF: /OMP_REDUCTION/a ObjectEntity INTEGER(4) integer a(10) - !DEF: /omp_reduction/b ObjectEntity INTEGER(4) + !DEF: /OMP_REDUCTION/b ObjectEntity INTEGER(4) integer b(10,10,10) !$omp parallel shared(k) !$omp do reduction(+:k) - !DEF: /omp_reduction/OtherConstruct1/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct1/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct1/OtherConstruct1/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct1/OtherConstruct1/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) k = k+1 end do !$omp end do @@ -24,53 +24,53 @@ program omp_reduction !$omp parallel do reduction(+:a(10)) - !DEF: /omp_reduction/OtherConstruct2/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct2/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct2/k (OmpShared) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct2/k (OmpShared) HostAssoc INTEGER(4) k = k+1 end do !$omp end parallel do !$omp parallel do reduction(+:a(1:10:1)) - !DEF: /omp_reduction/OtherConstruct3/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct3/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct3/k (OmpShared) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct3/k (OmpShared) HostAssoc INTEGER(4) k = k+1 end do !$omp end parallel do !$omp parallel do reduction(+:b(1:10:1,1:5,2)) - !DEF: /omp_reduction/OtherConstruct4/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct4/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct4/k (OmpShared) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct4/k (OmpShared) HostAssoc INTEGER(4) k = k+1 end do !$omp end parallel do !$omp parallel do reduction(+:b(1:10:1,1:5,2:5:1)) - !DEF: /omp_reduction/OtherConstruct5/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct5/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct5/k (OmpShared) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct5/k (OmpShared) HostAssoc INTEGER(4) k = k+1 end do !$omp end parallel do !$omp parallel private(i) !$omp do reduction(+:k) reduction(+:j) - !DEF: /omp_reduction/OtherConstruct6/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct6/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct6/OtherConstruct1/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct6/OtherConstruct1/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) k = k+1 end do !$omp end do !$omp end parallel !$omp do reduction(+:k) reduction(*:j) reduction(+:l) - !DEF: /omp_reduction/OtherConstruct7/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct7/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct7/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) + !DEF: /OMP_REDUCTION/OtherConstruct7/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) k = k+1 end do !$omp end do -end program omp_reduction +end program OMP_REDUCTION diff --git a/flang/test/Semantics/OpenMP/reduction11.f90 b/flang/test/Semantics/OpenMP/reduction11.f90 index b2ad0f6a6ee11..dfb3986d37d78 100644 --- a/flang/test/Semantics/OpenMP/reduction11.f90 +++ b/flang/test/Semantics/OpenMP/reduction11.f90 @@ -1,7 +1,7 @@ ! RUN: %flang_fc1 -fopenmp -fdebug-dump-symbols -o - %s 2>&1 | FileCheck %s ! Check intrinsic reduction symbols (in this case "max" are marked as INTRINSIC -! CHECK: MainProgram scope: omp_reduction +! CHECK: MainProgram scope: OMP_REDUCTION program omp_reduction ! CHECK: i size=4 offset=0: ObjectEntity type: INTEGER(4) integer i diff --git a/flang/test/Semantics/OpenMP/scan2.f90 b/flang/test/Semantics/OpenMP/scan2.f90 index ffe84910f88a2..1ae5e871595c4 100644 --- a/flang/test/Semantics/OpenMP/scan2.f90 +++ b/flang/test/Semantics/OpenMP/scan2.f90 @@ -1,7 +1,7 @@ ! RUN: %flang_fc1 -fopenmp -fdebug-dump-symbols -o - %s 2>&1 | FileCheck %s ! Check scan reduction -! CHECK: MainProgram scope: omp_reduction +! CHECK: MainProgram scope: OMP_REDUCTION program omp_reduction ! CHECK: i size=4 offset=0: ObjectEntity type: INTEGER(4) integer i diff --git a/flang/test/Semantics/OpenMP/symbol01.f90 b/flang/test/Semantics/OpenMP/symbol01.f90 index fbd9a0286c79b..74fb420cc517e 100644 --- a/flang/test/Semantics/OpenMP/symbol01.f90 +++ b/flang/test/Semantics/OpenMP/symbol01.f90 @@ -16,53 +16,53 @@ module md integer :: b end type myty end module md -!DEF: /mm MainProgram -program mm +!DEF: /MM MainProgram +program MM !REF: /md use :: md - !DEF: /mm/c CommonBlockDetails - !DEF: /mm/x (InCommonBlock) ObjectEntity REAL(4) - !DEF: /mm/y (InCommonBlock) ObjectEntity REAL(4) + !DEF: /MM/c CommonBlockDetails + !DEF: /MM/x (InCommonBlock) ObjectEntity REAL(4) + !DEF: /MM/y (InCommonBlock) ObjectEntity REAL(4) common /c/x, y - !REF: /mm/x - !REF: /mm/y + !REF: /MM/x + !REF: /MM/y real x, y - !DEF: /mm/myty Use - !DEF: /mm/t ObjectEntity TYPE(myty) + !DEF: /MM/myty Use + !DEF: /MM/t ObjectEntity TYPE(myty) type(myty) :: t - !DEF: /mm/b ObjectEntity INTEGER(4) + !DEF: /MM/b ObjectEntity INTEGER(4) integer b(10) - !REF: /mm/t + !REF: /MM/t !REF: /md/myty/a t%a = 3.14 - !REF: /mm/t + !REF: /MM/t !REF: /md/myty/b t%b = 1 - !REF: /mm/b + !REF: /MM/b b = 2 - !DEF: /mm/a (Implicit) ObjectEntity REAL(4) + !DEF: /MM/a (Implicit) ObjectEntity REAL(4) a = 1.0 - !DEF: /mm/c (Implicit) ObjectEntity REAL(4) + !DEF: /MM/c (Implicit) ObjectEntity REAL(4) c = 2.0 !$omp parallel do private(a,t,/c/) shared(c) - !DEF: /mm/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + !DEF: /MM/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /mm/OtherConstruct1/a (OmpPrivate, OmpExplicit) HostAssoc REAL(4) - !DEF: /mm/OtherConstruct1/b (OmpShared) HostAssoc INTEGER(4) - !REF: /mm/OtherConstruct1/i + !DEF: /MM/OtherConstruct1/a (OmpPrivate, OmpExplicit) HostAssoc REAL(4) + !DEF: /MM/OtherConstruct1/b (OmpShared) HostAssoc INTEGER(4) + !REF: /MM/OtherConstruct1/i a = a+b(i) - !DEF: /mm/OtherConstruct1/t (OmpPrivate, OmpExplicit) HostAssoc TYPE(myty) + !DEF: /MM/OtherConstruct1/t (OmpPrivate, OmpExplicit) HostAssoc TYPE(myty) !REF: /md/myty/a - !REF: /mm/OtherConstruct1/i + !REF: /MM/OtherConstruct1/i t%a = i - !DEF: /mm/OtherConstruct1/y (OmpPrivate, OmpExplicit) HostAssoc REAL(4) + !DEF: /MM/OtherConstruct1/y (OmpPrivate, OmpExplicit) HostAssoc REAL(4) y = 0. - !DEF: /mm/OtherConstruct1/x (OmpPrivate, OmpExplicit) HostAssoc REAL(4) - !REF: /mm/OtherConstruct1/a - !REF: /mm/OtherConstruct1/i - !REF: /mm/OtherConstruct1/y + !DEF: /MM/OtherConstruct1/x (OmpPrivate, OmpExplicit) HostAssoc REAL(4) + !REF: /MM/OtherConstruct1/a + !REF: /MM/OtherConstruct1/i + !REF: /MM/OtherConstruct1/y x = a+i+y - !DEF: /mm/OtherConstruct1/c (OmpShared, OmpExplicit) HostAssoc REAL(4) + !DEF: /MM/OtherConstruct1/c (OmpShared, OmpExplicit) HostAssoc REAL(4) c = 3.0 end do end program diff --git a/flang/test/Semantics/OpenMP/symbol05.f90 b/flang/test/Semantics/OpenMP/symbol05.f90 index fe01f15d20aa3..4f3d1926013dc 100644 --- a/flang/test/Semantics/OpenMP/symbol05.f90 +++ b/flang/test/Semantics/OpenMP/symbol05.f90 @@ -31,10 +31,10 @@ subroutine foo end block end subroutine foo end module mm -!DEF: /tt MainProgram -program tt +!DEF: /TT MainProgram +program TT !REF: /mm use :: mm - !DEF: /tt/foo (Subroutine) Use + !DEF: /TT/foo (Subroutine) Use call foo -end program tt +end program TT diff --git a/flang/test/Semantics/OpenMP/symbol07.f90 b/flang/test/Semantics/OpenMP/symbol07.f90 index 86b7305411347..1b0c25b7a04b0 100644 --- a/flang/test/Semantics/OpenMP/symbol07.f90 +++ b/flang/test/Semantics/OpenMP/symbol07.f90 @@ -30,8 +30,8 @@ subroutine function_call_in_region !REF: /function_call_in_region/b print *, a, b end subroutine function_call_in_region -!DEF: /mm MainProgram -program mm +!DEF: /MM MainProgram +program MM !REF: /function_call_in_region call function_call_in_region -end program mm +end program MM diff --git a/flang/test/Semantics/OpenMP/symbol09.f90 b/flang/test/Semantics/OpenMP/symbol09.f90 index 86b7305411347..1b0c25b7a04b0 100644 --- a/flang/test/Semantics/OpenMP/symbol09.f90 +++ b/flang/test/Semantics/OpenMP/symbol09.f90 @@ -30,8 +30,8 @@ subroutine function_call_in_region !REF: /function_call_in_region/b print *, a, b end subroutine function_call_in_region -!DEF: /mm MainProgram -program mm +!DEF: /MM MainProgram +program MM !REF: /function_call_in_region call function_call_in_region -end program mm +end program MM diff --git a/flang/test/Semantics/OpenMP/threadprivate03.f90 b/flang/test/Semantics/OpenMP/threadprivate03.f90 index 81e26ee327a9d..fda2fe608ac3c 100644 --- a/flang/test/Semantics/OpenMP/threadprivate03.f90 +++ b/flang/test/Semantics/OpenMP/threadprivate03.f90 @@ -10,11 +10,11 @@ program main use mod1 integer, parameter :: i = 1 - !ERROR: The module name or main program name cannot be in a THREADPRIVATE directive + !ERROR: The module name cannot be in a THREADPRIVATE directive !$omp threadprivate(mod1) - !PORTABILITY: Name 'main' declared in a main program should not have the same name as the main program [-Wbenign-name-clash] - !ERROR: The module name or main program name cannot be in a THREADPRIVATE directive + ! This is now allowed, since "main" is implicitly declared symbol, + ! separate from the main program symbol. !$omp threadprivate(main) !ERROR: The entity with PARAMETER attribute cannot be in a THREADPRIVATE directive diff --git a/flang/test/Semantics/PowerPC/ppc-vector-types01.f90 b/flang/test/Semantics/PowerPC/ppc-vector-types01.f90 index ad69b69a47f76..ea54a00fa4392 100644 --- a/flang/test/Semantics/PowerPC/ppc-vector-types01.f90 +++ b/flang/test/Semantics/PowerPC/ppc-vector-types01.f90 @@ -1,7 +1,7 @@ ! RUN: %flang_fc1 -fdebug-unparse %s | FileCheck %s ! REQUIRES: target=powerpc{{.*}} - ! CHECK-LABEL: PROGRAM ppc_vec_unit + ! CHECK-LABEL: PROGRAM PPC_VEC_UNIT program ppc_vec_unit implicit none ! CHECK: VECTOR(INTEGER(KIND=4_4)) :: vi1, vi2 diff --git a/flang/test/Semantics/PowerPC/ppc-vector-types02.f90 b/flang/test/Semantics/PowerPC/ppc-vector-types02.f90 index 8c96684c50eb7..175b58680a209 100644 --- a/flang/test/Semantics/PowerPC/ppc-vector-types02.f90 +++ b/flang/test/Semantics/PowerPC/ppc-vector-types02.f90 @@ -2,7 +2,7 @@ ! REQUIRES: target=powerpc{{.*}} ! C: MainProgram scope: ppc_vec_types -! CHECK-LABEL: MainProgram scope: ppc_vec_types size={{[0-9]*}} alignment={{[0-9]*}} +! CHECK-LABEL: MainProgram scope: PPC_VEC_TYPES size={{[0-9]*}} alignment={{[0-9]*}} program ppc_vec_types implicit none vector(integer(4)) :: vi diff --git a/flang/test/Semantics/bind-c18.f90 b/flang/test/Semantics/bind-c18.f90 new file mode 100644 index 0000000000000..f61111458c6d9 --- /dev/null +++ b/flang/test/Semantics/bind-c18.f90 @@ -0,0 +1,7 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 +bind(c) :: /blk/ +!ERROR: 'x' may not be a member of BIND(C) COMMON block /blk/ +common /blk/ x +!BECAUSE: A scalar interoperable variable may not be ALLOCATABLE or POINTER +integer, pointer :: x +end diff --git a/flang/test/Semantics/bug148559.f90 b/flang/test/Semantics/bug148559.f90 new file mode 100644 index 0000000000000..d7b959ac8f191 --- /dev/null +++ b/flang/test/Semantics/bug148559.f90 @@ -0,0 +1,12 @@ +!RUN: %flang_fc1 -fsyntax-only %s +!Regression test for crash in semantics on Cray pointers + +module m + pointer(ptr,pp) +end module m + +program main + use m, only:renamea=>pp + use m, only:pp + print *, renamea +end diff --git a/flang/test/Semantics/bug148675.f90 b/flang/test/Semantics/bug148675.f90 new file mode 100644 index 0000000000000..5ce117e7bb3df --- /dev/null +++ b/flang/test/Semantics/bug148675.f90 @@ -0,0 +1,21 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 +module m + type t + integer n + contains + procedure :: assign1 => myassign, assign2 => myassign + generic :: ASSIGNMENT(=) => assign1 + generic :: ASSIGNMENT(=) => assign2 + end type + contains + subroutine myassign(to, from) + class(t), intent(out) :: to + integer, intent(in) :: from + to%n = from + end + subroutine test + type(t) x + !ERROR: Multiple specific procedures for the generic ASSIGNMENT(=) match operand types TYPE(t) and INTEGER(4) + x = 5 + end +end diff --git a/flang/test/Semantics/getsymbols03-a.f90 b/flang/test/Semantics/getsymbols03-a.f90 index 95b7fb418367d..5c5e87575a9cb 100644 --- a/flang/test/Semantics/getsymbols03-a.f90 +++ b/flang/test/Semantics/getsymbols03-a.f90 @@ -8,7 +8,7 @@ program main end program ! RUN: %flang_fc1 -fget-symbols-sources %s 2>&1 | FileCheck %s +! CHECK:MAIN:{{.*}}getsymbols03-a.f90, 4, 9-13 ! CHECK:f:{{.*}}getsymbols03-b.f90, 2, 12-13 -! CHECK:main:{{.*}}getsymbols03-a.f90, 4, 9-13 ! CHECK:mm3:{{.*}}getsymbols03-a.f90, 5, 6-9 ! CHECK:x:{{.*}}getsymbols03-a.f90, 6, 13-14 diff --git a/flang/test/Semantics/long-name.f90 b/flang/test/Semantics/long-name.f90 index 44899b13edd5a..d5a795113e204 100644 --- a/flang/test/Semantics/long-name.f90 +++ b/flang/test/Semantics/long-name.f90 @@ -1,6 +1,6 @@ ! RUN: %python %S/test_errors.py %s %flang_fc1 -Werror -pedantic -!PORTABILITY: aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffggg1 has length 64, which is greater than the maximum name length 63 [-Wlong-names] +!PORTABILITY: AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDDEEEEEEEEEEFFFFFFFFFFGGG1 has length 64, which is greater than the maximum name length 63 [-Wlong-names] program aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffggg1 !PORTABILITY: aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffggg2 has length 64, which is greater than the maximum name length 63 [-Wlong-names] diff --git a/flang/test/Semantics/modproc01.f90 b/flang/test/Semantics/modproc01.f90 index 5f45362e95093..e565ddcfbe0b1 100644 --- a/flang/test/Semantics/modproc01.f90 +++ b/flang/test/Semantics/modproc01.f90 @@ -125,7 +125,7 @@ program test x = mf(3, "abc", pdt1(1,3)()) ! call ms(mf) end program -!CHECK: MainProgram scope: test size=88 alignment=8 +!CHECK: MainProgram scope: TEST size=88 alignment=8 !CHECK: mf, MODULE (Function): Use from mf in m !CHECK: pdt1: Use from pdt1 in m !CHECK: pdt2: Use from pdt2 in m diff --git a/flang/test/Semantics/multi-programs04.f90 b/flang/test/Semantics/multi-programs04.f90 index 54b0235aa78f0..e69ac7325278e 100644 --- a/flang/test/Semantics/multi-programs04.f90 +++ b/flang/test/Semantics/multi-programs04.f90 @@ -4,6 +4,6 @@ program m end !ERROR: A source file cannot contain more than one main program -!ERROR: 'm' is already declared in this scoping unit +!ERROR: 'M' is already declared in this scoping unit program m end diff --git a/flang/test/Semantics/pointer01.f90 b/flang/test/Semantics/pointer01.f90 index eaa2426dd77e3..79d6016a6af46 100644 --- a/flang/test/Semantics/pointer01.f90 +++ b/flang/test/Semantics/pointer01.f90 @@ -7,7 +7,6 @@ subroutine msubr end module program main use m - !PORTABILITY: Name 'main' declared in a main program should not have the same name as the main program [-Wbenign-name-clash] pointer main !ERROR: Cannot change POINTER attribute on use-associated 'mobj' pointer mobj diff --git a/flang/test/Semantics/procinterface01.f90 b/flang/test/Semantics/procinterface01.f90 index 73040b0987bd0..70f4a889d6809 100644 --- a/flang/test/Semantics/procinterface01.f90 +++ b/flang/test/Semantics/procinterface01.f90 @@ -159,35 +159,35 @@ end function logical tan = "?" end function tan -!DEF: /main MainProgram -program main +!DEF: /MAIN MainProgram +program MAIN !REF: /module1 use :: module1 - !DEF: /main/derived1 Use - !DEF: /main/instance ObjectEntity TYPE(derived1) + !DEF: /MAIN/derived1 Use + !DEF: /MAIN/instance ObjectEntity TYPE(derived1) type(derived1) :: instance - !REF: /main/instance + !REF: /MAIN/instance !REF: /module1/derived1/p1 if (instance%p1(1.)/=2.) print *, "p1 failed" - !REF: /main/instance + !REF: /MAIN/instance !REF: /module1/derived1/p2 if (instance%p2(1.)/=2.) print *, "p2 failed" - !REF: /main/instance + !REF: /MAIN/instance !REF: /module1/derived1/p3 if (.not.instance%p3(1.)) print *, "p3 failed" - !REF: /main/instance + !REF: /MAIN/instance !REF: /module1/derived1/p4 if (.not.instance%p4(1.)) print *, "p4 failed" - !REF: /main/instance + !REF: /MAIN/instance !REF: /module1/derived1/p5 if (instance%p5(1.)/=(5.,6.)) print *, "p5 failed" - !REF: /main/instance + !REF: /MAIN/instance !REF: /module1/derived1/p6 if (instance%p6(1.)/=2.) print *, "p6 failed" - !REF: /main/instance + !REF: /MAIN/instance !REF: /module1/derived1/p7 if (instance%p7(0.)/=1.) print *, "p7 failed" - !REF: /main/instance + !REF: /MAIN/instance !REF: /module1/derived1/p8 if (instance%p8(1.)/="a") print *, "p8 failed" -end program main +end program MAIN diff --git a/flang/test/Semantics/resolve05.f90 b/flang/test/Semantics/resolve05.f90 index 0c9877af9b4e2..7b142d2ebd613 100644 --- a/flang/test/Semantics/resolve05.f90 +++ b/flang/test/Semantics/resolve05.f90 @@ -1,6 +1,5 @@ ! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic program p - !PORTABILITY: Name 'p' declared in a main program should not have the same name as the main program [-Wbenign-name-clash] integer :: p end module m diff --git a/flang/test/Semantics/resolve125.f90 b/flang/test/Semantics/resolve125.f90 index e040c006ec179..620c7d65578cd 100644 --- a/flang/test/Semantics/resolve125.f90 +++ b/flang/test/Semantics/resolve125.f90 @@ -43,7 +43,7 @@ subroutine reset end subroutine reset end module m2 -!CHECK: MainProgram scope: main +!CHECK: MainProgram scope: MAIN !CHECK: i: Use from i in m2 !CHECK: i2: Use from i2 in m2 !CHECK: init (Subroutine): Use from init in m2 @@ -61,4 +61,4 @@ program main else print *, "fail" end if -end program main \ No newline at end of file +end program main diff --git a/flang/test/Semantics/resolve40.f90 b/flang/test/Semantics/resolve40.f90 index a91507aa62282..81bb5f989ec48 100644 --- a/flang/test/Semantics/resolve40.f90 +++ b/flang/test/Semantics/resolve40.f90 @@ -96,3 +96,10 @@ subroutine s12(x) !BECAUSE: 'x' is an INTENT(IN) dummy argument read(*,nml=nl) end + +subroutine s13() + implicit none + !ERROR: No explicit type declared for 'i' + !ERROR: No explicit type declared for 'i' + print *, (i, i = 1, 2) +end diff --git a/flang/test/Semantics/symbol03.f90 b/flang/test/Semantics/symbol03.f90 index a6b4b0bd15937..62472495d9736 100644 --- a/flang/test/Semantics/symbol03.f90 +++ b/flang/test/Semantics/symbol03.f90 @@ -1,23 +1,23 @@ ! RUN: %python %S/test_symbols.py %s %flang_fc1 ! Test host association in internal subroutine of main program. -!DEF: /main MainProgram -program main - !DEF: /main/x ObjectEntity INTEGER(4) +!DEF: /MAIN MainProgram +program MAIN + !DEF: /MAIN/x ObjectEntity INTEGER(4) integer x - !DEF: /main/s (Subroutine) Subprogram + !DEF: /MAIN/s (Subroutine) Subprogram call s contains - !REF: /main/s + !REF: /MAIN/s subroutine s - !DEF: /main/s/y (Implicit) ObjectEntity REAL(4) - !DEF: /main/s/x HostAssoc INTEGER(4) + !DEF: /MAIN/s/y (Implicit) ObjectEntity REAL(4) + !DEF: /MAIN/s/x HostAssoc INTEGER(4) y = x contains - !DEF: /main/s/s2 (Subroutine) Subprogram + !DEF: /MAIN/s/s2 (Subroutine) Subprogram subroutine s2 - !DEF: /main/s/s2/z (Implicit) ObjectEntity REAL(4) - !DEF: /main/s/s2/x HostAssoc INTEGER(4) + !DEF: /MAIN/s/s2/z (Implicit) ObjectEntity REAL(4) + !DEF: /MAIN/s/s2/x HostAssoc INTEGER(4) z = x end subroutine end subroutine diff --git a/flang/test/Semantics/symbol06.f90 b/flang/test/Semantics/symbol06.f90 index bbd6d4d071c89..b45edabcd5318 100644 --- a/flang/test/Semantics/symbol06.f90 +++ b/flang/test/Semantics/symbol06.f90 @@ -1,56 +1,56 @@ ! RUN: %python %S/test_symbols.py %s %flang_fc1 -!DEF: /main MainProgram -program main - !DEF: /main/t1 DerivedType +!DEF: /MAIN MainProgram +program MAIN + !DEF: /MAIN/t1 DerivedType type :: t1 - !DEF: /main/t1/a1 ObjectEntity INTEGER(4) + !DEF: /MAIN/t1/a1 ObjectEntity INTEGER(4) integer :: a1 end type - !REF: /main/t1 - !DEF: /main/t2 DerivedType + !REF: /MAIN/t1 + !DEF: /MAIN/t2 DerivedType type, extends(t1) :: t2 - !DEF: /main/t2/a2 ObjectEntity INTEGER(4) + !DEF: /MAIN/t2/a2 ObjectEntity INTEGER(4) integer :: a2 end type - !REF: /main/t2 - !DEF: /main/t3 DerivedType + !REF: /MAIN/t2 + !DEF: /MAIN/t3 DerivedType type, extends(t2) :: t3 - !DEF: /main/t3/a3 ObjectEntity INTEGER(4) + !DEF: /MAIN/t3/a3 ObjectEntity INTEGER(4) integer :: a3 end type - !REF: /main/t3 - !DEF: /main/x3 ObjectEntity TYPE(t3) + !REF: /MAIN/t3 + !DEF: /MAIN/x3 ObjectEntity TYPE(t3) type(t3) :: x3 - !DEF: /main/i ObjectEntity INTEGER(4) + !DEF: /MAIN/i ObjectEntity INTEGER(4) integer i - !REF: /main/i - !REF: /main/x3 - !REF: /main/t2/a2 + !REF: /MAIN/i + !REF: /MAIN/x3 + !REF: /MAIN/t2/a2 i = x3%a2 - !REF: /main/i - !REF: /main/x3 - !REF: /main/t1/a1 + !REF: /MAIN/i + !REF: /MAIN/x3 + !REF: /MAIN/t1/a1 i = x3%a1 - !REF: /main/i - !REF: /main/x3 - !DEF: /main/t3/t2 (ParentComp) ObjectEntity TYPE(t2) - !REF: /main/t2/a2 + !REF: /MAIN/i + !REF: /MAIN/x3 + !DEF: /MAIN/t3/t2 (ParentComp) ObjectEntity TYPE(t2) + !REF: /MAIN/t2/a2 i = x3%t2%a2 - !REF: /main/i - !REF: /main/x3 - !REF: /main/t3/t2 - !REF: /main/t1/a1 + !REF: /MAIN/i + !REF: /MAIN/x3 + !REF: /MAIN/t3/t2 + !REF: /MAIN/t1/a1 i = x3%t2%a1 - !REF: /main/i - !REF: /main/x3 - !DEF: /main/t2/t1 (ParentComp) ObjectEntity TYPE(t1) - !REF: /main/t1/a1 + !REF: /MAIN/i + !REF: /MAIN/x3 + !DEF: /MAIN/t2/t1 (ParentComp) ObjectEntity TYPE(t1) + !REF: /MAIN/t1/a1 i = x3%t1%a1 - !REF: /main/i - !REF: /main/x3 - !REF: /main/t3/t2 - !REF: /main/t2/t1 - !REF: /main/t1/a1 + !REF: /MAIN/i + !REF: /MAIN/x3 + !REF: /MAIN/t3/t2 + !REF: /MAIN/t2/t1 + !REF: /MAIN/t1/a1 i = x3%t2%t1%a1 end program diff --git a/flang/test/Semantics/symbol07.f90 b/flang/test/Semantics/symbol07.f90 index f3cc934e51b16..e1d8257b9e190 100644 --- a/flang/test/Semantics/symbol07.f90 +++ b/flang/test/Semantics/symbol07.f90 @@ -1,40 +1,40 @@ ! RUN: %python %S/test_symbols.py %s %flang_fc1 -!DEF: /main MainProgram -program main +!DEF: /MAIN MainProgram +program MAIN implicit complex(z) - !DEF: /main/t DerivedType + !DEF: /MAIN/t DerivedType type :: t - !DEF: /main/t/re ObjectEntity REAL(4) + !DEF: /MAIN/t/re ObjectEntity REAL(4) real :: re - !DEF: /main/t/im ObjectEntity REAL(4) + !DEF: /MAIN/t/im ObjectEntity REAL(4) real :: im end type - !DEF: /main/z1 ObjectEntity COMPLEX(4) + !DEF: /MAIN/z1 ObjectEntity COMPLEX(4) complex z1 - !REF: /main/t - !DEF: /main/w ObjectEntity TYPE(t) + !REF: /MAIN/t + !DEF: /MAIN/w ObjectEntity TYPE(t) type(t) :: w - !DEF: /main/x ObjectEntity REAL(4) - !DEF: /main/y ObjectEntity REAL(4) + !DEF: /MAIN/x ObjectEntity REAL(4) + !DEF: /MAIN/y ObjectEntity REAL(4) real x, y - !REF: /main/x - !REF: /main/z1 + !REF: /MAIN/x + !REF: /MAIN/z1 x = z1%re - !REF: /main/y - !REF: /main/z1 + !REF: /MAIN/y + !REF: /MAIN/z1 y = z1%im - !DEF: /main/z2 (Implicit) ObjectEntity COMPLEX(4) - !REF: /main/x + !DEF: /MAIN/z2 (Implicit) ObjectEntity COMPLEX(4) + !REF: /MAIN/x z2%re = x - !REF: /main/z2 - !REF: /main/y + !REF: /MAIN/z2 + !REF: /MAIN/y z2%im = y - !REF: /main/x - !REF: /main/w - !REF: /main/t/re + !REF: /MAIN/x + !REF: /MAIN/w + !REF: /MAIN/t/re x = w%re - !REF: /main/y - !REF: /main/w - !REF: /main/t/im + !REF: /MAIN/y + !REF: /MAIN/w + !REF: /MAIN/t/im y = w%im end program diff --git a/flang/test/Semantics/symbol08.f90 b/flang/test/Semantics/symbol08.f90 index 61dab798955c5..933ff6d0c2ba8 100644 --- a/flang/test/Semantics/symbol08.f90 +++ b/flang/test/Semantics/symbol08.f90 @@ -1,15 +1,15 @@ ! RUN: %python %S/test_symbols.py %s %flang_fc1 -!DEF: /main MainProgram -program main - !DEF: /main/x POINTER ObjectEntity REAL(4) +!DEF: /MAIN MainProgram +program MAIN + !DEF: /MAIN/x POINTER ObjectEntity REAL(4) pointer :: x - !REF: /main/x + !REF: /MAIN/x real x - !DEF: /main/y EXTERNAL, POINTER (Function) ProcEntity REAL(4) + !DEF: /MAIN/y EXTERNAL, POINTER (Function) ProcEntity REAL(4) pointer :: y - !REF: /main/y + !REF: /MAIN/y procedure (real) :: y - !DEF: /main/z (Implicit) ObjectEntity REAL(4) - !REF: /main/y + !DEF: /MAIN/z (Implicit) ObjectEntity REAL(4) + !REF: /MAIN/y z = y() end program diff --git a/flang/test/Semantics/symbol15.f90 b/flang/test/Semantics/symbol15.f90 index df10942e6af2d..79a45491306ef 100644 --- a/flang/test/Semantics/symbol15.f90 +++ b/flang/test/Semantics/symbol15.f90 @@ -249,15 +249,15 @@ subroutine ext2 !DEF: /ext3 (Subroutine) Subprogram subroutine ext3 end subroutine -!DEF: /main MainProgram -program main +!DEF: /MAIN MainProgram +program MAIN !REF: /m use :: m - !DEF: /main/pdt1 Use - !DEF: /main/pdt1y ObjectEntity TYPE(pdt1(k=2_4)) + !DEF: /MAIN/pdt1 Use + !DEF: /MAIN/pdt1y ObjectEntity TYPE(pdt1(k=2_4)) type(pdt1(2)) :: pdt1y - !DEF: /main/pdt2 Use - !DEF: /main/pdt2y ObjectEntity TYPE(pdt2(k=2_4)) + !DEF: /MAIN/pdt2 Use + !DEF: /MAIN/pdt2y ObjectEntity TYPE(pdt2(k=2_4)) type(pdt2(2)) :: pdt2y print *, "compiled" end program diff --git a/flang/test/Semantics/symbol16.f90 b/flang/test/Semantics/symbol16.f90 index 7a46092c36b53..547c4624d4cdb 100644 --- a/flang/test/Semantics/symbol16.f90 +++ b/flang/test/Semantics/symbol16.f90 @@ -1,18 +1,18 @@ ! RUN: %python %S/test_symbols.py %s %flang_fc1 ! Statement functions -!DEF: /p1 MainProgram -program p1 - !DEF: /p1/f (Function, StmtFunction) Subprogram INTEGER(4) - !DEF: /p1/i ObjectEntity INTEGER(4) - !DEF: /p1/j ObjectEntity INTEGER(4) +!DEF: /P1 MainProgram +program P1 + !DEF: /P1/f (Function, StmtFunction) Subprogram INTEGER(4) + !DEF: /P1/i ObjectEntity INTEGER(4) + !DEF: /P1/j ObjectEntity INTEGER(4) integer f, i, j - !REF: /p1/f - !REF: /p1/i - !DEF: /p1/f/i ObjectEntity INTEGER(4) + !REF: /P1/f + !REF: /P1/i + !DEF: /P1/f/i ObjectEntity INTEGER(4) f(i) = i + 1 - !REF: /p1/j - !REF: /p1/f + !REF: /P1/j + !REF: /P1/f j = f(2) end program diff --git a/flang/test/Semantics/symbol17.f90 b/flang/test/Semantics/symbol17.f90 index 434f124509a32..a0d916e55cfa4 100644 --- a/flang/test/Semantics/symbol17.f90 +++ b/flang/test/Semantics/symbol17.f90 @@ -1,44 +1,44 @@ ! RUN: %python %S/test_symbols.py %s %flang_fc1 ! Forward references to derived types (non-error cases) -!DEF: /main MainProgram -program main - !DEF: /main/t1 DerivedType +!DEF: /MAIN MainProgram +program MAIN + !DEF: /MAIN/t1 DerivedType type :: t1 - !DEF: /main/t2 DerivedType - !DEF: /main/t1/t1a ALLOCATABLE ObjectEntity TYPE(t2) + !DEF: /MAIN/t2 DerivedType + !DEF: /MAIN/t1/t1a ALLOCATABLE ObjectEntity TYPE(t2) type(t2), allocatable :: t1a - !REF: /main/t2 - !DEF: /main/t1/t1p POINTER ObjectEntity TYPE(t2) + !REF: /MAIN/t2 + !DEF: /MAIN/t1/t1p POINTER ObjectEntity TYPE(t2) type(t2), pointer :: t1p end type - !REF: /main/t2 + !REF: /MAIN/t2 type :: t2 - !REF: /main/t2 - !DEF: /main/t2/t2a ALLOCATABLE ObjectEntity TYPE(t2) + !REF: /MAIN/t2 + !DEF: /MAIN/t2/t2a ALLOCATABLE ObjectEntity TYPE(t2) type(t2), allocatable :: t2a - !REF: /main/t2 - !DEF: /main/t2/t2p POINTER ObjectEntity TYPE(t2) + !REF: /MAIN/t2 + !DEF: /MAIN/t2/t2p POINTER ObjectEntity TYPE(t2) type(t2), pointer :: t2p end type - !REF: /main/t1 - !DEF: /main/t1x TARGET ObjectEntity TYPE(t1) + !REF: /MAIN/t1 + !DEF: /MAIN/t1x TARGET ObjectEntity TYPE(t1) type(t1), target :: t1x - !REF: /main/t1x - !REF: /main/t1/t1a + !REF: /MAIN/t1x + !REF: /MAIN/t1/t1a allocate(t1x%t1a) - !REF: /main/t1x - !REF: /main/t1/t1p - !REF: /main/t1/t1a + !REF: /MAIN/t1x + !REF: /MAIN/t1/t1p + !REF: /MAIN/t1/t1a t1x%t1p => t1x%t1a - !REF: /main/t1x - !REF: /main/t1/t1a - !REF: /main/t2/t2a + !REF: /MAIN/t1x + !REF: /MAIN/t1/t1a + !REF: /MAIN/t2/t2a allocate(t1x%t1a%t2a) - !REF: /main/t1x - !REF: /main/t1/t1a - !REF: /main/t2/t2p - !REF: /main/t2/t2a + !REF: /MAIN/t1x + !REF: /MAIN/t1/t1a + !REF: /MAIN/t2/t2p + !REF: /MAIN/t2/t2a t1x%t1a%t2p => t1x%t1a%t2a end program !DEF: /f1/fwd DerivedType diff --git a/flang/test/Semantics/symbol18.f90 b/flang/test/Semantics/symbol18.f90 index a37792bce21d7..6e41bb5db91ee 100644 --- a/flang/test/Semantics/symbol18.f90 +++ b/flang/test/Semantics/symbol18.f90 @@ -2,21 +2,21 @@ ! Intrinsic function in type declaration statement: type is ignored -!DEF: /p1 MainProgram -program p1 - !DEF: /p1/cos ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity INTEGER(4) +!DEF: /P1 MainProgram +program P1 + !DEF: /P1/cos ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity INTEGER(4) integer cos - !DEF: /p1/y (Implicit) ObjectEntity REAL(4) - !REF: /p1/cos - !DEF: /p1/x (Implicit) ObjectEntity REAL(4) + !DEF: /P1/y (Implicit) ObjectEntity REAL(4) + !REF: /P1/cos + !DEF: /P1/x (Implicit) ObjectEntity REAL(4) y = cos(x) - !REF: /p1/y - !DEF: /p1/sin ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity - !REF: /p1/x + !REF: /P1/y + !DEF: /P1/sin ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity + !REF: /P1/x y = sin(x) - !REF: /p1/y + !REF: /P1/y !DEF: /f EXTERNAL (Function, Implicit) ProcEntity REAL(4) - !REF: /p1/x + !REF: /P1/x y = f(x) end program diff --git a/flang/test/Semantics/symbol20.f90 b/flang/test/Semantics/symbol20.f90 index 8c82776933321..bf3aff489b3b9 100644 --- a/flang/test/Semantics/symbol20.f90 +++ b/flang/test/Semantics/symbol20.f90 @@ -32,16 +32,16 @@ subroutine bar print *, "in bar" end subroutine end module -!DEF: /demo MainProgram -program demo +!DEF: /DEMO MainProgram +program DEMO !REF: /m use :: m - !DEF: /demo/bar (Subroutine) Use - !DEF: /demo/p EXTERNAL, POINTER (Subroutine) ProcEntity + !DEF: /DEMO/bar (Subroutine) Use + !DEF: /DEMO/p EXTERNAL, POINTER (Subroutine) ProcEntity procedure(bar), pointer :: p - !REF: /demo/p - !DEF: /demo/foo (Function) Use + !REF: /DEMO/p + !DEF: /DEMO/foo (Function) Use p => foo() - !REF: /demo/p + !REF: /DEMO/p call p end program diff --git a/flang/test/Semantics/symbol25.f90 b/flang/test/Semantics/symbol25.f90 index ac3dd37ef92eb..ac47a19eae8cc 100644 --- a/flang/test/Semantics/symbol25.f90 +++ b/flang/test/Semantics/symbol25.f90 @@ -38,23 +38,23 @@ subroutine inner1 end subroutine inner1 end subroutine outer end module m -!DEF: /main MainProgram -program main +!DEF: /MAIN MainProgram +program MAIN !REF: /m use :: m !REF: /m/specific1 call generic - !DEF: /main/inner2 (Subroutine) Subprogram + !DEF: /MAIN/inner2 (Subroutine) Subprogram call inner2 contains - !REF: /main/inner2 + !REF: /MAIN/inner2 subroutine inner2 - !DEF: /main/inner2/generic (Subroutine) Generic + !DEF: /MAIN/inner2/generic (Subroutine) Generic interface generic - !DEF: /main/specific2 (Subroutine) Use + !DEF: /MAIN/specific2 (Subroutine) Use module procedure :: specific2 end interface - !REF: /main/specific2 + !REF: /MAIN/specific2 call generic end subroutine inner2 end program diff --git a/flang/test/Semantics/symbol26.f90 b/flang/test/Semantics/symbol26.f90 index f5e95853ca099..dded4b632c654 100644 --- a/flang/test/Semantics/symbol26.f90 +++ b/flang/test/Semantics/symbol26.f90 @@ -8,16 +8,16 @@ module m !DEF: /m/j PUBLIC (Implicit, InNamelist) ObjectEntity INTEGER(4) namelist/a/j end module m -!DEF: /main MainProgram -program main - !DEF: /main/j (Implicit) ObjectEntity INTEGER(4) +!DEF: /MAIN MainProgram +program MAIN + !DEF: /MAIN/j (Implicit) ObjectEntity INTEGER(4) j = 1 contains - !DEF: /main/inner (Subroutine) Subprogram + !DEF: /MAIN/inner (Subroutine) Subprogram subroutine inner !REF: /m use :: m - !DEF: /main/inner/j (Implicit, InNamelist) Use INTEGER(4) + !DEF: /MAIN/inner/j (Implicit, InNamelist) Use INTEGER(4) j = 2 end subroutine end program diff --git a/flang/test/Semantics/typeinfo01.f90 b/flang/test/Semantics/typeinfo01.f90 index bb20c546e0261..aeec336ea58ea 100644 --- a/flang/test/Semantics/typeinfo01.f90 +++ b/flang/test/Semantics/typeinfo01.f90 @@ -87,8 +87,8 @@ subroutine s2(x, y) !CHECK: .c.t2, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:0_8 init:[component::component(name=.n.t,genre=1_1,category=6_1,kind=0_1,rank=0_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),derived=.dt.t,lenvalue=NULL(),bounds=NULL(),initialization=NULL())] !CHECK: .dt.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=.v.t,name=.n.t,sizeinbytes=0_8,uninstantiated=NULL(),kindparameter=NULL(),lenparameterkind=NULL(),component=NULL(),procptr=NULL(),special=.s.t,specialbitset=2_4,hasparent=0_1,noinitializationneeded=1_1,nodestructionneeded=1_1,nofinalizationneeded=1_1,nodefinedassignment=0_1) !CHECK: .dt.t2, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=.v.t2,name=.n.t2,sizeinbytes=0_8,uninstantiated=NULL(),kindparameter=NULL(),lenparameterkind=NULL(),component=.c.t2,procptr=NULL(),special=.s.t2,specialbitset=2_4,hasparent=1_1,noinitializationneeded=1_1,nodestructionneeded=1_1,nofinalizationneeded=1_1,nodefinedassignment=0_1) -!CHECK: .s.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=1_1,isargdescriptorset=3_1,istypebound=1_1,isargcontiguousset=0_1,proc=s1)] -!CHECK: .s.t2, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=1_1,isargdescriptorset=3_1,istypebound=1_1,isargcontiguousset=0_1,proc=s2)] +!CHECK: .s.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=1_1,isargdescriptorset=3_1,istypebound=1_1,specialcaseflag=0_1,proc=s1)] +!CHECK: .s.t2, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=1_1,isargdescriptorset=3_1,istypebound=1_1,specialcaseflag=0_1,proc=s2)] !CHECK: .v.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(binding) shape: 0_8:0_8 init:[binding::binding(proc=s1,name=.n.s1)] !CHECK: .v.t2, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(binding) shape: 0_8:0_8 init:[binding::binding(proc=s2,name=.n.s1)] end module @@ -115,8 +115,8 @@ subroutine s2(x, y) !CHECK: .c.t2, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:0_8 init:[component::component(name=.n.t,genre=1_1,category=6_1,kind=0_1,rank=0_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),derived=.dt.t,lenvalue=NULL(),bounds=NULL(),initialization=NULL())] !CHECK: .dt.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=.v.t,name=.n.t,sizeinbytes=0_8,uninstantiated=NULL(),kindparameter=NULL(),lenparameterkind=NULL(),component=NULL(),procptr=NULL(),special=.s.t,specialbitset=2_4,hasparent=0_1,noinitializationneeded=1_1,nodestructionneeded=1_1,nofinalizationneeded=1_1,nodefinedassignment=0_1) !CHECK: .dt.t2, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=.v.t2,name=.n.t2,sizeinbytes=0_8,uninstantiated=NULL(),kindparameter=NULL(),lenparameterkind=NULL(),component=.c.t2,procptr=NULL(),special=.s.t2,specialbitset=2_4,hasparent=1_1,noinitializationneeded=1_1,nodestructionneeded=1_1,nofinalizationneeded=1_1,nodefinedassignment=0_1) -!CHECK: .s.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=1_1,isargdescriptorset=3_1,istypebound=1_1,isargcontiguousset=0_1,proc=s1)] -!CHECK: .s.t2, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=1_1,isargdescriptorset=3_1,istypebound=1_1,isargcontiguousset=0_1,proc=s2)] +!CHECK: .s.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=1_1,isargdescriptorset=3_1,istypebound=1_1,specialcaseflag=0_1,proc=s1)] +!CHECK: .s.t2, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=1_1,isargdescriptorset=3_1,istypebound=1_1,specialcaseflag=0_1,proc=s2)] !CHECK: .v.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(binding) shape: 0_8:0_8 init:[binding::binding(proc=s1,name=.n.s1)] !CHECK: .v.t2, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(binding) shape: 0_8:0_8 init:[binding::binding(proc=s2,name=.n.s1)] end module @@ -133,7 +133,7 @@ impure elemental subroutine s1(x, y) class(t), intent(in) :: y end subroutine !CHECK: .dt.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=.v.t,name=.n.t,sizeinbytes=0_8,uninstantiated=NULL(),kindparameter=NULL(),lenparameterkind=NULL(),component=NULL(),procptr=NULL(),special=.s.t,specialbitset=4_4,hasparent=0_1,noinitializationneeded=1_1,nodestructionneeded=1_1,nofinalizationneeded=1_1,nodefinedassignment=0_1) -!CHECK: .s.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=2_1,isargdescriptorset=3_1,istypebound=1_1,isargcontiguousset=0_1,proc=s1)] +!CHECK: .s.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=2_1,isargdescriptorset=3_1,istypebound=1_1,specialcaseflag=0_1,proc=s1)] !CHECK: .v.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(binding) shape: 0_8:0_8 init:[binding::binding(proc=s1,name=.n.s1)] end module @@ -156,7 +156,7 @@ subroutine s4(x) type(t), contiguous :: x(:,:,:) end subroutine !CHECK: .dt.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=NULL(),name=.n.t,sizeinbytes=0_8,uninstantiated=NULL(),kindparameter=NULL(),lenparameterkind=NULL(),component=NULL(),procptr=NULL(),special=.s.t,specialbitset=7296_4,hasparent=0_1,noinitializationneeded=1_1,nodestructionneeded=0_1,nofinalizationneeded=0_1,nodefinedassignment=1_1) -!CHECK: .s.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:3_8 init:[specialbinding::specialbinding(which=7_1,isargdescriptorset=0_1,istypebound=0_1,isargcontiguousset=0_1,proc=s3),specialbinding(which=10_1,isargdescriptorset=1_1,istypebound=0_1,isargcontiguousset=0_1,proc=s1),specialbinding(which=11_1,isargdescriptorset=0_1,istypebound=0_1,isargcontiguousset=1_1,proc=s2),specialbinding(which=12_1,isargdescriptorset=1_1,istypebound=0_1,isargcontiguousset=1_1,proc=s4)] +!CHECK: .s.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:3_8 init:[specialbinding::specialbinding(which=7_1,isargdescriptorset=0_1,istypebound=0_1,specialcaseflag=0_1,proc=s3),specialbinding(which=10_1,isargdescriptorset=1_1,istypebound=0_1,specialcaseflag=0_1,proc=s1),specialbinding(which=11_1,isargdescriptorset=0_1,istypebound=0_1,specialcaseflag=1_1,proc=s2),specialbinding(which=12_1,isargdescriptorset=1_1,istypebound=0_1,specialcaseflag=1_1,proc=s4)] end module module m09 @@ -198,7 +198,7 @@ subroutine wu(x,u,iostat,iomsg) character(len=*), intent(inout) :: iomsg end subroutine !CHECK: .dt.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=.v.t,name=.n.t,sizeinbytes=0_8,uninstantiated=NULL(),kindparameter=NULL(),lenparameterkind=NULL(),component=NULL(),procptr=NULL(),special=.s.t,specialbitset=120_4,hasparent=0_1,noinitializationneeded=1_1,nodestructionneeded=1_1,nofinalizationneeded=1_1,nodefinedassignment=1_1) -!CHECK: .s.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:3_8 init:[specialbinding::specialbinding(which=3_1,isargdescriptorset=1_1,istypebound=1_1,isargcontiguousset=0_1,proc=rf),specialbinding(which=4_1,isargdescriptorset=1_1,istypebound=2_1,isargcontiguousset=0_1,proc=ru),specialbinding(which=5_1,isargdescriptorset=1_1,istypebound=3_1,isargcontiguousset=0_1,proc=wf),specialbinding(which=6_1,isargdescriptorset=1_1,istypebound=4_1,isargcontiguousset=0_1,proc=wu)] +!CHECK: .s.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:3_8 init:[specialbinding::specialbinding(which=3_1,isargdescriptorset=1_1,istypebound=1_1,specialcaseflag=0_1,proc=rf),specialbinding(which=4_1,isargdescriptorset=1_1,istypebound=2_1,specialcaseflag=0_1,proc=ru),specialbinding(which=5_1,isargdescriptorset=1_1,istypebound=3_1,specialcaseflag=0_1,proc=wf),specialbinding(which=6_1,isargdescriptorset=1_1,istypebound=4_1,specialcaseflag=0_1,proc=wu)] !CHECK: .v.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(binding) shape: 0_8:3_8 init:[binding::binding(proc=rf,name=.n.rf),binding(proc=ru,name=.n.ru),binding(proc=wf,name=.n.wf),binding(proc=wu,name=.n.wu)] end module @@ -247,7 +247,7 @@ subroutine wu(x,u,iostat,iomsg) character(len=*), intent(inout) :: iomsg end subroutine !CHECK: .dt.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=NULL(),name=.n.t,sizeinbytes=0_8,uninstantiated=NULL(),kindparameter=NULL(),lenparameterkind=NULL(),component=NULL(),procptr=NULL(),special=.s.t,specialbitset=120_4,hasparent=0_1,noinitializationneeded=1_1,nodestructionneeded=1_1,nofinalizationneeded=1_1,nodefinedassignment=1_1) -!CHECK: .s.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:3_8 init:[specialbinding::specialbinding(which=3_1,isargdescriptorset=0_1,istypebound=0_1,isargcontiguousset=0_1,proc=rf),specialbinding(which=4_1,isargdescriptorset=0_1,istypebound=0_1,isargcontiguousset=0_1,proc=ru),specialbinding(which=5_1,isargdescriptorset=0_1,istypebound=0_1,isargcontiguousset=0_1,proc=wf),specialbinding(which=6_1,isargdescriptorset=0_1,istypebound=0_1,isargcontiguousset=0_1,proc=wu)] +!CHECK: .s.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:3_8 init:[specialbinding::specialbinding(which=3_1,isargdescriptorset=0_1,istypebound=0_1,specialcaseflag=0_1,proc=rf),specialbinding(which=4_1,isargdescriptorset=0_1,istypebound=0_1,specialcaseflag=0_1,proc=ru),specialbinding(which=5_1,isargdescriptorset=0_1,istypebound=0_1,specialcaseflag=0_1,proc=wf),specialbinding(which=6_1,isargdescriptorset=0_1,istypebound=0_1,specialcaseflag=0_1,proc=wu)] end module module m11 @@ -290,7 +290,7 @@ module m13 contains procedure :: assign1, assign2 generic :: assignment(=) => assign1, assign2 - ! CHECK: .s.t1, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=2_1,isargdescriptorset=3_1,istypebound=1_1,isargcontiguousset=0_1,proc=assign1)] + ! CHECK: .s.t1, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=2_1,isargdescriptorset=3_1,istypebound=1_1,specialcaseflag=0_1,proc=assign1)] end type contains impure elemental subroutine assign1(to, from) diff --git a/flang/test/Semantics/typeinfo02.f90 b/flang/test/Semantics/typeinfo02.f90 index 29d14c7a0f196..07293627ab492 100644 --- a/flang/test/Semantics/typeinfo02.f90 +++ b/flang/test/Semantics/typeinfo02.f90 @@ -29,5 +29,5 @@ subroutine wf2(x,u,iot,v,iostat,iomsg) character(len=*), intent(inout) :: iomsg end subroutine end module -!CHECK: .s.base, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=5_1,isargdescriptorset=1_1,istypebound=1_1,isargcontiguousset=0_1,proc=wf1)] -!CHECK: .s.extended, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=5_1,isargdescriptorset=1_1,istypebound=1_1,isargcontiguousset=0_1,proc=wf2)] +!CHECK: .s.base, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=5_1,isargdescriptorset=1_1,istypebound=1_1,specialcaseflag=0_1,proc=wf1)] +!CHECK: .s.extended, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=5_1,isargdescriptorset=1_1,istypebound=1_1,specialcaseflag=0_1,proc=wf2)] diff --git a/flang/test/Semantics/typeinfo09.f90 b/flang/test/Semantics/typeinfo09.f90 index 3527ee6058ad8..8daa6a5f420d7 100644 --- a/flang/test/Semantics/typeinfo09.f90 +++ b/flang/test/Semantics/typeinfo09.f90 @@ -17,4 +17,4 @@ subroutine copy_impl(this, x) end interface end module -!CHECK: .s.sometype, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=1_1,isargdescriptorset=1_1,istypebound=1_1,isargcontiguousset=0_1,proc=copy_impl)] +!CHECK: .s.sometype, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=1_1,isargdescriptorset=1_1,istypebound=1_1,specialcaseflag=0_1,proc=copy_impl)] diff --git a/flang/test/Semantics/typeinfo13.f90 b/flang/test/Semantics/typeinfo13.f90 index ad824ad3590a2..facc280815722 100644 --- a/flang/test/Semantics/typeinfo13.f90 +++ b/flang/test/Semantics/typeinfo13.f90 @@ -22,5 +22,5 @@ impure elemental subroutine override(to, from) end end -!CHECK: .s.child, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=2_1,isargdescriptorset=1_1,istypebound=2_1,isargcontiguousset=0_1,proc=override)] +!CHECK: .s.child, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=2_1,isargdescriptorset=1_1,istypebound=2_1,specialcaseflag=0_1,proc=override)] !CHECK: .v.child, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(binding) shape: 0_8:1_8 init:[binding::binding(proc=baseassign,name=.n.baseassign),binding(proc=override,name=.n.override)] diff --git a/flang/test/Transforms/DoConcurrent/basic_host.f90 b/flang/test/Transforms/DoConcurrent/basic_host.f90 index 12f63031cbaee..6f24b346e3fb9 100644 --- a/flang/test/Transforms/DoConcurrent/basic_host.f90 +++ b/flang/test/Transforms/DoConcurrent/basic_host.f90 @@ -5,7 +5,7 @@ ! RUN: bbc -emit-hlfir -fopenmp -fdo-concurrent-to-openmp=host %s -o - \ ! RUN: | FileCheck %s -! CHECK-LABEL: do_concurrent_basic +! CHECK-LABEL: DO_CONCURRENT_BASIC program do_concurrent_basic ! CHECK: %[[ARR:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) diff --git a/flang/test/Transforms/lower-repack-arrays.fir b/flang/test/Transforms/lower-repack-arrays.fir index 458869cce45fd..9232a74f224d3 100644 --- a/flang/test/Transforms/lower-repack-arrays.fir +++ b/flang/test/Transforms/lower-repack-arrays.fir @@ -28,15 +28,14 @@ func.func @_QPtest1(%arg0: !fir.box> {fir.bindc_name = "x"}) // CHECK: %[[VAL_17:.*]] = fir.shape %[[VAL_15]]#1, %[[VAL_16]]#1 : (index, index) -> !fir.shape<2> // CHECK: %[[VAL_18:.*]] = fir.allocmem !fir.array, %[[VAL_15]]#1, %[[VAL_16]]#1 {bindc_name = ".repacked", uniq_name = ""} // CHECK: %[[VAL_19:.*]] = fir.declare %[[VAL_18]](%[[VAL_17]]) {uniq_name = ".repacked"} : (!fir.heap>, !fir.shape<2>) -> !fir.heap> -// CHECK: %[[VAL_20:.*]] = fir.embox %[[VAL_19]](%[[VAL_17]]) : (!fir.heap>, !fir.shape<2>) -> !fir.box>> +// CHECK: %[[VAL_25:.*]] = fir.shape_shift %[[VAL_15]]#0, %[[VAL_15]]#1, %[[VAL_16]]#0, %[[VAL_16]]#1 : (index, index, index, index) -> !fir.shapeshift<2> +// CHECK: %[[VAL_20:.*]] = fir.embox %[[VAL_19]](%[[VAL_25]]) : (!fir.heap>, !fir.shapeshift<2>) -> !fir.box> // CHECK: %[[VAL_21:.*]] = fir.address_of(@{{_QQcl.*}} -// CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_20]] : (!fir.box>>) -> !fir.box +// CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_20]] : (!fir.box>) -> !fir.box // CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_0]] : (!fir.box>) -> !fir.box // CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_21]] : (!fir.ref>) -> !fir.ref // CHECK: fir.call @_FortranAShallowCopyDirect(%[[VAL_22]], %[[VAL_23]], %[[VAL_24]], %[[VAL_2]]) : (!fir.box, !fir.box, !fir.ref, i32) -> () -// CHECK: %[[VAL_25:.*]] = fir.shift %[[VAL_15]]#0, %[[VAL_16]]#0 : (index, index) -> !fir.shift<2> -// CHECK: %[[VAL_26:.*]] = fir.rebox %[[VAL_20]](%[[VAL_25]]) : (!fir.box>>, !fir.shift<2>) -> !fir.box> -// CHECK: fir.result %[[VAL_26]] : !fir.box> +// CHECK: fir.result %[[VAL_20]] : !fir.box> // CHECK: } else { // CHECK: fir.result %[[VAL_0]] : !fir.box> // CHECK: } @@ -93,15 +92,14 @@ func.func @_QPtest1_whole(%arg0: !fir.box> {fir.bindc_name = // CHECK: %[[VAL_17:.*]] = fir.shape %[[VAL_15]]#1, %[[VAL_16]]#1 : (index, index) -> !fir.shape<2> // CHECK: %[[VAL_18:.*]] = fir.alloca !fir.array, %[[VAL_15]]#1, %[[VAL_16]]#1 {bindc_name = ".repacked"} // CHECK: %[[VAL_19:.*]] = fir.declare %[[VAL_18]](%[[VAL_17]]) {uniq_name = ".repacked"} : (!fir.ref>, !fir.shape<2>) -> !fir.ref> -// CHECK: %[[VAL_20:.*]] = fir.embox %[[VAL_19]](%[[VAL_17]]) : (!fir.ref>, !fir.shape<2>) -> !fir.box> +// CHECK: %[[VAL_25:.*]] = fir.shape_shift %[[VAL_15]]#0, %[[VAL_15]]#1, %[[VAL_16]]#0, %[[VAL_16]]#1 : (index, index, index, index) -> !fir.shapeshift<2> +// CHECK: %[[VAL_20:.*]] = fir.embox %[[VAL_19]](%[[VAL_25]]) : (!fir.ref>, !fir.shapeshift<2>) -> !fir.box> // CHECK: %[[VAL_21:.*]] = fir.address_of(@{{_QQcl.*}} // CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_20]] : (!fir.box>) -> !fir.box // CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_0]] : (!fir.box>) -> !fir.box // CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_21]] : (!fir.ref>) -> !fir.ref // CHECK: fir.call @_FortranAShallowCopyDirect(%[[VAL_22]], %[[VAL_23]], %[[VAL_24]], %[[VAL_2]]) : (!fir.box, !fir.box, !fir.ref, i32) -> () -// CHECK: %[[VAL_25:.*]] = fir.shift %[[VAL_15]]#0, %[[VAL_16]]#0 : (index, index) -> !fir.shift<2> -// CHECK: %[[VAL_26:.*]] = fir.rebox %[[VAL_20]](%[[VAL_25]]) : (!fir.box>, !fir.shift<2>) -> !fir.box> -// CHECK: fir.result %[[VAL_26]] : !fir.box> +// CHECK: fir.result %[[VAL_20]] : !fir.box> // CHECK: } else { // CHECK: fir.result %[[VAL_0]] : !fir.box> // CHECK: } @@ -156,15 +154,14 @@ func.func @_QPtest1_in(%arg0: !fir.box> {fir.bindc_name = "x // CHECK: %[[VAL_16:.*]] = fir.shape %[[VAL_14]]#1, %[[VAL_15]]#1 : (index, index) -> !fir.shape<2> // CHECK: %[[VAL_17:.*]] = fir.allocmem !fir.array, %[[VAL_14]]#1, %[[VAL_15]]#1 {bindc_name = ".repacked", uniq_name = ""} // CHECK: %[[VAL_18:.*]] = fir.declare %[[VAL_17]](%[[VAL_16]]) {uniq_name = ".repacked"} : (!fir.heap>, !fir.shape<2>) -> !fir.heap> -// CHECK: %[[VAL_19:.*]] = fir.embox %[[VAL_18]](%[[VAL_16]]) : (!fir.heap>, !fir.shape<2>) -> !fir.box>> +// CHECK: %[[VAL_24:.*]] = fir.shape_shift %[[VAL_14]]#0, %[[VAL_14]]#1, %[[VAL_15]]#0, %[[VAL_15]]#1 : (index, index, index, index) -> !fir.shapeshift<2> +// CHECK: %[[VAL_19:.*]] = fir.embox %[[VAL_18]](%[[VAL_24]]) : (!fir.heap>, !fir.shapeshift<2>) -> !fir.box> // CHECK: %[[VAL_20:.*]] = fir.address_of(@{{_QQcl.*}} -// CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_19]] : (!fir.box>>) -> !fir.box +// CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_19]] : (!fir.box>) -> !fir.box // CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_0]] : (!fir.box>) -> !fir.box // CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_20]] : (!fir.ref>) -> !fir.ref // CHECK: fir.call @_FortranAShallowCopyDirect(%[[VAL_21]], %[[VAL_22]], %[[VAL_23]], %[[VAL_1]]) : (!fir.box, !fir.box, !fir.ref, i32) -> () -// CHECK: %[[VAL_24:.*]] = fir.shift %[[VAL_14]]#0, %[[VAL_15]]#0 : (index, index) -> !fir.shift<2> -// CHECK: %[[VAL_25:.*]] = fir.rebox %[[VAL_19]](%[[VAL_24]]) : (!fir.box>>, !fir.shift<2>) -> !fir.box> -// CHECK: fir.result %[[VAL_25]] : !fir.box> +// CHECK: fir.result %[[VAL_19]] : !fir.box> // CHECK: } else { // CHECK: fir.result %[[VAL_0]] : !fir.box> // CHECK: } @@ -215,10 +212,9 @@ func.func @_QPtest1_out(%arg0: !fir.box> {fir.bindc_name = " // CHECK: %[[VAL_16:.*]] = fir.shape %[[VAL_14]]#1, %[[VAL_15]]#1 : (index, index) -> !fir.shape<2> // CHECK: %[[VAL_17:.*]] = fir.allocmem !fir.array, %[[VAL_14]]#1, %[[VAL_15]]#1 {bindc_name = ".repacked", uniq_name = ""} // CHECK: %[[VAL_18:.*]] = fir.declare %[[VAL_17]](%[[VAL_16]]) {uniq_name = ".repacked"} : (!fir.heap>, !fir.shape<2>) -> !fir.heap> -// CHECK: %[[VAL_19:.*]] = fir.embox %[[VAL_18]](%[[VAL_16]]) : (!fir.heap>, !fir.shape<2>) -> !fir.box>> -// CHECK: %[[VAL_20:.*]] = fir.shift %[[VAL_14]]#0, %[[VAL_15]]#0 : (index, index) -> !fir.shift<2> -// CHECK: %[[VAL_21:.*]] = fir.rebox %[[VAL_19]](%[[VAL_20]]) : (!fir.box>>, !fir.shift<2>) -> !fir.box> -// CHECK: fir.result %[[VAL_21]] : !fir.box> +// CHECK: %[[VAL_20:.*]] = fir.shape_shift %[[VAL_14]]#0, %[[VAL_14]]#1, %[[VAL_15]]#0, %[[VAL_15]]#1 : (index, index, index, index) -> !fir.shapeshift<2> +// CHECK: %[[VAL_19:.*]] = fir.embox %[[VAL_18]](%[[VAL_20]]) : (!fir.heap>, !fir.shapeshift<2>) -> !fir.box> +// CHECK: fir.result %[[VAL_19]] : !fir.box> // CHECK: } else { // CHECK: fir.result %[[VAL_0]] : !fir.box> // CHECK: } @@ -286,15 +282,14 @@ func.func @_QPtest2(%arg0: !fir.ref {fir.bindc_name = "n"}, %arg1: !fir.box // CHECK: %[[VAL_23:.*]] = fir.shape %[[VAL_21]]#1, %[[VAL_22]]#1 : (index, index) -> !fir.shape<2> // CHECK: %[[VAL_24:.*]] = fir.allocmem !fir.array>(%[[VAL_12]] : i32), %[[VAL_21]]#1, %[[VAL_22]]#1 {bindc_name = ".repacked", uniq_name = ""} // CHECK: %[[VAL_25:.*]] = fir.declare %[[VAL_24]](%[[VAL_23]]) typeparams %[[VAL_12]] {uniq_name = ".repacked"} : (!fir.heap>>, !fir.shape<2>, i32) -> !fir.heap>> -// CHECK: %[[VAL_26:.*]] = fir.embox %[[VAL_25]](%[[VAL_23]]) typeparams %[[VAL_12]] : (!fir.heap>>, !fir.shape<2>, i32) -> !fir.box>>> +// CHECK: %[[VAL_31:.*]] = fir.shape_shift %[[VAL_21]]#0, %[[VAL_21]]#1, %[[VAL_22]]#0, %[[VAL_22]]#1 : (index, index, index, index) -> !fir.shapeshift<2> +// CHECK: %[[VAL_26:.*]] = fir.embox %[[VAL_25]](%[[VAL_31]]) typeparams %[[VAL_12]] : (!fir.heap>>, !fir.shapeshift<2>, i32) -> !fir.box>> // CHECK: %[[VAL_27:.*]] = fir.address_of(@{{_QQcl.*}} -// CHECK: %[[VAL_28:.*]] = fir.convert %[[VAL_26]] : (!fir.box>>>) -> !fir.box +// CHECK: %[[VAL_28:.*]] = fir.convert %[[VAL_26]] : (!fir.box>>) -> !fir.box // CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_1]] : (!fir.box>>) -> !fir.box // CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_27]] : (!fir.ref>) -> !fir.ref // CHECK: fir.call @_FortranAShallowCopyDirect(%[[VAL_28]], %[[VAL_29]], %[[VAL_30]], %[[VAL_3]]) : (!fir.box, !fir.box, !fir.ref, i32) -> () -// CHECK: %[[VAL_31:.*]] = fir.shift %[[VAL_21]]#0, %[[VAL_22]]#0 : (index, index) -> !fir.shift<2> -// CHECK: %[[VAL_32:.*]] = fir.rebox %[[VAL_26]](%[[VAL_31]]) : (!fir.box>>>, !fir.shift<2>) -> !fir.box>> -// CHECK: fir.result %[[VAL_32]] : !fir.box>> +// CHECK: fir.result %[[VAL_26]] : !fir.box>> // CHECK: } else { // CHECK: fir.result %[[VAL_1]] : !fir.box>> // CHECK: } @@ -362,15 +357,14 @@ func.func @_QPtest2_stack(%arg0: !fir.ref {fir.bindc_name = "n"}, %arg1: !f // CHECK: %[[VAL_23:.*]] = fir.shape %[[VAL_21]]#1, %[[VAL_22]]#1 : (index, index) -> !fir.shape<2> // CHECK: %[[VAL_24:.*]] = fir.alloca !fir.array>(%[[VAL_12]] : i32), %[[VAL_21]]#1, %[[VAL_22]]#1 {bindc_name = ".repacked"} // CHECK: %[[VAL_25:.*]] = fir.declare %[[VAL_24]](%[[VAL_23]]) typeparams %[[VAL_12]] {uniq_name = ".repacked"} : (!fir.ref>>, !fir.shape<2>, i32) -> !fir.ref>> -// CHECK: %[[VAL_26:.*]] = fir.embox %[[VAL_25]](%[[VAL_23]]) typeparams %[[VAL_12]] : (!fir.ref>>, !fir.shape<2>, i32) -> !fir.box>> +// CHECK: %[[VAL_31:.*]] = fir.shape_shift %[[VAL_21]]#0, %[[VAL_21]]#1, %[[VAL_22]]#0, %[[VAL_22]]#1 : (index, index, index, index) -> !fir.shapeshift<2> +// CHECK: %[[VAL_26:.*]] = fir.embox %[[VAL_25]](%[[VAL_31]]) typeparams %[[VAL_12]] : (!fir.ref>>, !fir.shapeshift<2>, i32) -> !fir.box>> // CHECK: %[[VAL_27:.*]] = fir.address_of(@{{_QQcl.*}} // CHECK: %[[VAL_28:.*]] = fir.convert %[[VAL_26]] : (!fir.box>>) -> !fir.box // CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_1]] : (!fir.box>>) -> !fir.box // CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_27]] : (!fir.ref>) -> !fir.ref // CHECK: fir.call @_FortranAShallowCopyDirect(%[[VAL_28]], %[[VAL_29]], %[[VAL_30]], %[[VAL_3]]) : (!fir.box, !fir.box, !fir.ref, i32) -> () -// CHECK: %[[VAL_31:.*]] = fir.shift %[[VAL_21]]#0, %[[VAL_22]]#0 : (index, index) -> !fir.shift<2> -// CHECK: %[[VAL_32:.*]] = fir.rebox %[[VAL_26]](%[[VAL_31]]) : (!fir.box>>, !fir.shift<2>) -> !fir.box>> -// CHECK: fir.result %[[VAL_32]] : !fir.box>> +// CHECK: fir.result %[[VAL_26]] : !fir.box>> // CHECK: } else { // CHECK: fir.result %[[VAL_1]] : !fir.box>> // CHECK: } @@ -427,15 +421,14 @@ func.func @_QPtest3(%arg0: !fir.box>> {fir.bindc_n // CHECK: %[[VAL_18:.*]] = fir.shape %[[VAL_15]]#1, %[[VAL_16]]#1 : (index, index) -> !fir.shape<2> // CHECK: %[[VAL_19:.*]] = fir.allocmem !fir.array>(%[[VAL_17]] : index), %[[VAL_15]]#1, %[[VAL_16]]#1 {bindc_name = ".repacked", uniq_name = ""} // CHECK: %[[VAL_20:.*]] = fir.declare %[[VAL_19]](%[[VAL_18]]) typeparams %[[VAL_17]] {uniq_name = ".repacked"} : (!fir.heap>>, !fir.shape<2>, index) -> !fir.heap>> -// CHECK: %[[VAL_21:.*]] = fir.embox %[[VAL_20]](%[[VAL_18]]) typeparams %[[VAL_17]] : (!fir.heap>>, !fir.shape<2>, index) -> !fir.box>>> +// CHECK: %[[VAL_26:.*]] = fir.shape_shift %[[VAL_15]]#0, %[[VAL_15]]#1, %[[VAL_16]]#0, %[[VAL_16]]#1 : (index, index, index, index) -> !fir.shapeshift<2> +// CHECK: %[[VAL_21:.*]] = fir.embox %[[VAL_20]](%[[VAL_26]]) typeparams %[[VAL_17]] : (!fir.heap>>, !fir.shapeshift<2>, index) -> !fir.box>> // CHECK: %[[VAL_22:.*]] = fir.address_of(@{{_QQcl.*}} -// CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.box>>>) -> !fir.box +// CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.box>>) -> !fir.box // CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_0]] : (!fir.box>>) -> !fir.box // CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_22]] : (!fir.ref>) -> !fir.ref // CHECK: fir.call @_FortranAShallowCopyDirect(%[[VAL_23]], %[[VAL_24]], %[[VAL_25]], %[[VAL_2]]) : (!fir.box, !fir.box, !fir.ref, i32) -> () -// CHECK: %[[VAL_26:.*]] = fir.shift %[[VAL_15]]#0, %[[VAL_16]]#0 : (index, index) -> !fir.shift<2> -// CHECK: %[[VAL_27:.*]] = fir.rebox %[[VAL_21]](%[[VAL_26]]) : (!fir.box>>>, !fir.shift<2>) -> !fir.box>> -// CHECK: fir.result %[[VAL_27]] : !fir.box>> +// CHECK: fir.result %[[VAL_21]] : !fir.box>> // CHECK: } else { // CHECK: fir.result %[[VAL_0]] : !fir.box>> // CHECK: } @@ -493,15 +486,14 @@ func.func @_QPtest3_stack(%arg0: !fir.box>> {fir.b // CHECK: %[[VAL_18:.*]] = fir.shape %[[VAL_15]]#1, %[[VAL_16]]#1 : (index, index) -> !fir.shape<2> // CHECK: %[[VAL_19:.*]] = fir.alloca !fir.array>(%[[VAL_17]] : index), %[[VAL_15]]#1, %[[VAL_16]]#1 {bindc_name = ".repacked"} // CHECK: %[[VAL_20:.*]] = fir.declare %[[VAL_19]](%[[VAL_18]]) typeparams %[[VAL_17]] {uniq_name = ".repacked"} : (!fir.ref>>, !fir.shape<2>, index) -> !fir.ref>> -// CHECK: %[[VAL_21:.*]] = fir.embox %[[VAL_20]](%[[VAL_18]]) typeparams %[[VAL_17]] : (!fir.ref>>, !fir.shape<2>, index) -> !fir.box>> +// CHECK: %[[VAL_26:.*]] = fir.shape_shift %[[VAL_15]]#0, %[[VAL_15]]#1, %[[VAL_16]]#0, %[[VAL_16]]#1 : (index, index, index, index) -> !fir.shapeshift<2> +// CHECK: %[[VAL_21:.*]] = fir.embox %[[VAL_20]](%[[VAL_26]]) typeparams %[[VAL_17]] : (!fir.ref>>, !fir.shapeshift<2>, index) -> !fir.box>> // CHECK: %[[VAL_22:.*]] = fir.address_of(@{{_QQcl.*}} // CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.box>>) -> !fir.box // CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_0]] : (!fir.box>>) -> !fir.box // CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_22]] : (!fir.ref>) -> !fir.ref // CHECK: fir.call @_FortranAShallowCopyDirect(%[[VAL_23]], %[[VAL_24]], %[[VAL_25]], %[[VAL_2]]) : (!fir.box, !fir.box, !fir.ref, i32) -> () -// CHECK: %[[VAL_26:.*]] = fir.shift %[[VAL_15]]#0, %[[VAL_16]]#0 : (index, index) -> !fir.shift<2> -// CHECK: %[[VAL_27:.*]] = fir.rebox %[[VAL_21]](%[[VAL_26]]) : (!fir.box>>, !fir.shift<2>) -> !fir.box>> -// CHECK: fir.result %[[VAL_27]] : !fir.box>> +// CHECK: fir.result %[[VAL_21]] : !fir.box>> // CHECK: } else { // CHECK: fir.result %[[VAL_0]] : !fir.box>> // CHECK: } @@ -559,15 +551,14 @@ func.func @_QPtest4(%arg0: !fir.box>> {fir.bindc_ // CHECK: %[[VAL_18:.*]] = fir.shape %[[VAL_16]]#1, %[[VAL_17]]#1 : (index, index) -> !fir.shape<2> // CHECK: %[[VAL_19:.*]] = fir.allocmem !fir.array>, %[[VAL_16]]#1, %[[VAL_17]]#1 {bindc_name = ".repacked", uniq_name = ""} // CHECK: %[[VAL_20:.*]] = fir.declare %[[VAL_19]](%[[VAL_18]]) typeparams %[[VAL_6]] {uniq_name = ".repacked"} : (!fir.heap>>, !fir.shape<2>, index) -> !fir.heap>> -// CHECK: %[[VAL_21:.*]] = fir.embox %[[VAL_20]](%[[VAL_18]]) : (!fir.heap>>, !fir.shape<2>) -> !fir.box>>> +// CHECK: %[[VAL_26:.*]] = fir.shape_shift %[[VAL_16]]#0, %[[VAL_16]]#1, %[[VAL_17]]#0, %[[VAL_17]]#1 : (index, index, index, index) -> !fir.shapeshift<2> +// CHECK: %[[VAL_21:.*]] = fir.embox %[[VAL_20]](%[[VAL_26]]) : (!fir.heap>>, !fir.shapeshift<2>) -> !fir.box>> // CHECK: %[[VAL_22:.*]] = fir.address_of(@{{_QQcl.*}} -// CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.box>>>) -> !fir.box +// CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.box>>) -> !fir.box // CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_0]] : (!fir.box>>) -> !fir.box // CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_22]] : (!fir.ref>) -> !fir.ref // CHECK: fir.call @_FortranAShallowCopyDirect(%[[VAL_23]], %[[VAL_24]], %[[VAL_25]], %[[VAL_2]]) : (!fir.box, !fir.box, !fir.ref, i32) -> () -// CHECK: %[[VAL_26:.*]] = fir.shift %[[VAL_16]]#0, %[[VAL_17]]#0 : (index, index) -> !fir.shift<2> -// CHECK: %[[VAL_27:.*]] = fir.rebox %[[VAL_21]](%[[VAL_26]]) : (!fir.box>>>, !fir.shift<2>) -> !fir.box>> -// CHECK: fir.result %[[VAL_27]] : !fir.box>> +// CHECK: fir.result %[[VAL_21]] : !fir.box>> // CHECK: } else { // CHECK: fir.result %[[VAL_0]] : !fir.box>> // CHECK: } @@ -626,15 +617,14 @@ func.func @_QPtest4_stack(%arg0: !fir.box>> {fir. // CHECK: %[[VAL_18:.*]] = fir.shape %[[VAL_16]]#1, %[[VAL_17]]#1 : (index, index) -> !fir.shape<2> // CHECK: %[[VAL_19:.*]] = fir.alloca !fir.array>, %[[VAL_16]]#1, %[[VAL_17]]#1 {bindc_name = ".repacked"} // CHECK: %[[VAL_20:.*]] = fir.declare %[[VAL_19]](%[[VAL_18]]) typeparams %[[VAL_6]] {uniq_name = ".repacked"} : (!fir.ref>>, !fir.shape<2>, index) -> !fir.ref>> -// CHECK: %[[VAL_21:.*]] = fir.embox %[[VAL_20]](%[[VAL_18]]) : (!fir.ref>>, !fir.shape<2>) -> !fir.box>> +// CHECK: %[[VAL_26:.*]] = fir.shape_shift %[[VAL_16]]#0, %[[VAL_16]]#1, %[[VAL_17]]#0, %[[VAL_17]]#1 : (index, index, index, index) -> !fir.shapeshift<2> +// CHECK: %[[VAL_21:.*]] = fir.embox %[[VAL_20]](%[[VAL_26]]) : (!fir.ref>>, !fir.shapeshift<2>) -> !fir.box>> // CHECK: %[[VAL_22:.*]] = fir.address_of(@{{_QQcl.*}} // CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.box>>) -> !fir.box // CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_0]] : (!fir.box>>) -> !fir.box // CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_22]] : (!fir.ref>) -> !fir.ref // CHECK: fir.call @_FortranAShallowCopyDirect(%[[VAL_23]], %[[VAL_24]], %[[VAL_25]], %[[VAL_2]]) : (!fir.box, !fir.box, !fir.ref, i32) -> () -// CHECK: %[[VAL_26:.*]] = fir.shift %[[VAL_16]]#0, %[[VAL_17]]#0 : (index, index) -> !fir.shift<2> -// CHECK: %[[VAL_27:.*]] = fir.rebox %[[VAL_21]](%[[VAL_26]]) : (!fir.box>>, !fir.shift<2>) -> !fir.box>> -// CHECK: fir.result %[[VAL_27]] : !fir.box>> +// CHECK: fir.result %[[VAL_21]] : !fir.box>> // CHECK: } else { // CHECK: fir.result %[[VAL_0]] : !fir.box>> // CHECK: } @@ -690,15 +680,15 @@ func.func @_QPtest5(%arg0: !fir.box>> {fir.bind // CHECK: %[[VAL_17:.*]] = fir.shape %[[VAL_15]]#1, %[[VAL_16]]#1 : (index, index) -> !fir.shape<2> // CHECK: %[[VAL_18:.*]] = fir.allocmem !fir.array>, %[[VAL_15]]#1, %[[VAL_16]]#1 {bindc_name = ".repacked", uniq_name = ""} // CHECK: %[[VAL_19:.*]] = fir.declare %[[VAL_18]](%[[VAL_17]]) {uniq_name = ".repacked"} : (!fir.heap>>, !fir.shape<2>) -> !fir.heap>> -// CHECK: %[[VAL_20:.*]] = fir.embox %[[VAL_19]](%[[VAL_17]]) : (!fir.heap>>, !fir.shape<2>) -> !fir.box>>> +// CHECK: %[[VAL_25:.*]] = fir.shape_shift %[[VAL_15]]#0, %[[VAL_15]]#1, %[[VAL_16]]#0, %[[VAL_16]]#1 : (index, index, index, index) -> !fir.shapeshift<2> +// CHECK: %[[VAL_20:.*]] = fir.embox %[[VAL_19]](%[[VAL_25]]) source_box %[[VAL_0]] : (!fir.heap>>, !fir.shapeshift<2>, !fir.box>>) -> !fir.class>> +// CHECK: %[[BOX:.*]] = fir.convert %[[VAL_20]] : (!fir.class>>) -> !fir.box>> // CHECK: %[[VAL_21:.*]] = fir.address_of(@{{_QQcl.*}} -// CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_20]] : (!fir.box>>>) -> !fir.box +// CHECK: %[[VAL_22:.*]] = fir.convert %[[BOX]] : (!fir.box>>) -> !fir.box // CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_0]] : (!fir.box>>) -> !fir.box // CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_21]] : (!fir.ref>) -> !fir.ref // CHECK: fir.call @_FortranAShallowCopyDirect(%[[VAL_22]], %[[VAL_23]], %[[VAL_24]], %[[VAL_2]]) : (!fir.box, !fir.box, !fir.ref, i32) -> () -// CHECK: %[[VAL_25:.*]] = fir.shift %[[VAL_15]]#0, %[[VAL_16]]#0 : (index, index) -> !fir.shift<2> -// CHECK: %[[VAL_26:.*]] = fir.rebox %[[VAL_20]](%[[VAL_25]]) : (!fir.box>>>, !fir.shift<2>) -> !fir.box>> -// CHECK: fir.result %[[VAL_26]] : !fir.box>> +// CHECK: fir.result %[[BOX]] : !fir.box>> // CHECK: } else { // CHECK: fir.result %[[VAL_0]] : !fir.box>> // CHECK: } @@ -755,15 +745,15 @@ func.func @_QPtest5_stack(%arg0: !fir.box>> {fi // CHECK: %[[VAL_17:.*]] = fir.shape %[[VAL_15]]#1, %[[VAL_16]]#1 : (index, index) -> !fir.shape<2> // CHECK: %[[VAL_18:.*]] = fir.alloca !fir.array>, %[[VAL_15]]#1, %[[VAL_16]]#1 {bindc_name = ".repacked"} // CHECK: %[[VAL_19:.*]] = fir.declare %[[VAL_18]](%[[VAL_17]]) {uniq_name = ".repacked"} : (!fir.ref>>, !fir.shape<2>) -> !fir.ref>> -// CHECK: %[[VAL_20:.*]] = fir.embox %[[VAL_19]](%[[VAL_17]]) : (!fir.ref>>, !fir.shape<2>) -> !fir.box>> +// CHECK: %[[VAL_25:.*]] = fir.shape_shift %[[VAL_15]]#0, %[[VAL_15]]#1, %[[VAL_16]]#0, %[[VAL_16]]#1 : (index, index, index, index) -> !fir.shapeshift<2> +// CHECK: %[[VAL_20:.*]] = fir.embox %[[VAL_19]](%[[VAL_25]]) source_box %[[VAL_0]] : (!fir.ref>>, !fir.shapeshift<2>, !fir.box>>) -> !fir.class>> +// CHECK: %[[BOX:.*]] = fir.convert %[[VAL_20]] : (!fir.class>>) -> !fir.box>> // CHECK: %[[VAL_21:.*]] = fir.address_of(@{{_QQcl.*}} -// CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_20]] : (!fir.box>>) -> !fir.box +// CHECK: %[[VAL_22:.*]] = fir.convert %[[BOX]] : (!fir.box>>) -> !fir.box // CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_0]] : (!fir.box>>) -> !fir.box // CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_21]] : (!fir.ref>) -> !fir.ref // CHECK: fir.call @_FortranAShallowCopyDirect(%[[VAL_22]], %[[VAL_23]], %[[VAL_24]], %[[VAL_2]]) : (!fir.box, !fir.box, !fir.ref, i32) -> () -// CHECK: %[[VAL_25:.*]] = fir.shift %[[VAL_15]]#0, %[[VAL_16]]#0 : (index, index) -> !fir.shift<2> -// CHECK: %[[VAL_26:.*]] = fir.rebox %[[VAL_20]](%[[VAL_25]]) : (!fir.box>>, !fir.shift<2>) -> !fir.box>> -// CHECK: fir.result %[[VAL_26]] : !fir.box>> +// CHECK: fir.result %[[BOX]] : !fir.box>> // CHECK: } else { // CHECK: fir.result %[[VAL_0]] : !fir.box>> // CHECK: } @@ -830,13 +820,14 @@ func.func @_QPtest6(%arg0: !fir.class>> {fir.bi // CHECK: %[[VAL_26:.*]] = fir.call @_FortranAAllocatableAllocate(%[[VAL_23]], %[[VAL_24]], %[[VAL_4]], %[[VAL_22]], %[[VAL_25]], %[[VAL_1]]) : (!fir.ref>, !fir.ref, i1, !fir.box, !fir.ref, i32) -> i32 // CHECK: %[[VAL_27:.*]] = fir.load %[[VAL_5]] : !fir.ref>>>> // CHECK: %[[VAL_28:.*]] = fir.declare %[[VAL_27]] {uniq_name = ".repacked"} : (!fir.class>>>) -> !fir.class>>> +// CHECK: %[[ADDR:.*]] = fir.box_addr %[[VAL_28]] : (!fir.class>>>) -> !fir.heap>> +// CHECK: %[[VAL_33:.*]] = fir.shape_shift %[[VAL_15]]#0, %[[VAL_15]]#1, %[[VAL_16]]#0, %[[VAL_16]]#1 : (index, index, index, index) -> !fir.shapeshift<2> +// CHECK: %[[VAL_34:.*]] = fir.embox %[[ADDR]](%[[VAL_33]]) source_box %[[ARG0]] : (!fir.heap>>, !fir.shapeshift<2>, !fir.class>>) -> !fir.class>> // CHECK: %[[VAL_29:.*]] = fir.address_of(@{{_QQcl.*}}) : !fir.ref> -// CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_28]] : (!fir.class>>>) -> !fir.box +// CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_34]] : (!fir.class>>) -> !fir.box // CHECK: %[[VAL_31:.*]] = fir.convert %[[ARG0]] : (!fir.class>>) -> !fir.box // CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_29]] : (!fir.ref>) -> !fir.ref // CHECK: fir.call @_FortranAShallowCopyDirect(%[[VAL_30]], %[[VAL_31]], %[[VAL_32]], %[[VAL_1]]) : (!fir.box, !fir.box, !fir.ref, i32) -> () -// CHECK: %[[VAL_33:.*]] = fir.shift %[[VAL_15]]#0, %[[VAL_16]]#0 : (index, index) -> !fir.shift<2> -// CHECK: %[[VAL_34:.*]] = fir.rebox %[[VAL_28]](%[[VAL_33]]) : (!fir.class>>>, !fir.shift<2>) -> !fir.class>> // CHECK: fir.result %[[VAL_34]] : !fir.class>> // CHECK: } else { // CHECK: fir.result %[[ARG0]] : !fir.class>> @@ -906,13 +897,14 @@ func.func @_QPtest6_stack(%arg0: !fir.class>> { // CHECK: %[[VAL_26:.*]] = fir.call @_FortranAAllocatableAllocate(%[[VAL_23]], %[[VAL_24]], %[[VAL_4]], %[[VAL_22]], %[[VAL_25]], %[[VAL_1]]) : (!fir.ref>, !fir.ref, i1, !fir.box, !fir.ref, i32) -> i32 // CHECK: %[[VAL_27:.*]] = fir.load %[[VAL_5]] : !fir.ref>>>> // CHECK: %[[VAL_28:.*]] = fir.declare %[[VAL_27]] {uniq_name = ".repacked"} : (!fir.class>>>) -> !fir.class>>> +// CHECK: %[[ADDR:.*]] = fir.box_addr %[[VAL_28]] : (!fir.class>>>) -> !fir.heap>> +// CHECK: %[[VAL_33:.*]] = fir.shape_shift %[[VAL_15]]#0, %[[VAL_15]]#1, %[[VAL_16]]#0, %[[VAL_16]]#1 : (index, index, index, index) -> !fir.shapeshift<2> +// CHECK: %[[VAL_34:.*]] = fir.embox %[[ADDR]](%[[VAL_33]]) source_box %[[ARG0]] : (!fir.heap>>, !fir.shapeshift<2>, !fir.class>>) -> !fir.class>> // CHECK: %[[VAL_29:.*]] = fir.address_of(@{{_QQcl.*}}) : !fir.ref> -// CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_28]] : (!fir.class>>>) -> !fir.box +// CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_34]] : (!fir.class>>) -> !fir.box // CHECK: %[[VAL_31:.*]] = fir.convert %[[ARG0]] : (!fir.class>>) -> !fir.box // CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_29]] : (!fir.ref>) -> !fir.ref // CHECK: fir.call @_FortranAShallowCopyDirect(%[[VAL_30]], %[[VAL_31]], %[[VAL_32]], %[[VAL_1]]) : (!fir.box, !fir.box, !fir.ref, i32) -> () -// CHECK: %[[VAL_33:.*]] = fir.shift %[[VAL_15]]#0, %[[VAL_16]]#0 : (index, index) -> !fir.shift<2> -// CHECK: %[[VAL_34:.*]] = fir.rebox %[[VAL_28]](%[[VAL_33]]) : (!fir.class>>>, !fir.shift<2>) -> !fir.class>> // CHECK: fir.result %[[VAL_34]] : !fir.class>> // CHECK: } else { // CHECK: fir.result %[[ARG0]] : !fir.class>> @@ -981,13 +973,14 @@ func.func @_QPtest7(%arg0: !fir.class> {fir.bindc_name = "x // CHECK: %[[VAL_26:.*]] = fir.call @_FortranAAllocatableAllocate(%[[VAL_23]], %[[VAL_24]], %[[VAL_4]], %[[VAL_22]], %[[VAL_25]], %[[VAL_1]]) : (!fir.ref>, !fir.ref, i1, !fir.box, !fir.ref, i32) -> i32 // CHECK: %[[VAL_27:.*]] = fir.load %[[VAL_5]] : !fir.ref>>> // CHECK: %[[VAL_28:.*]] = fir.declare %[[VAL_27]] {uniq_name = ".repacked"} : (!fir.class>>) -> !fir.class>> +// CHECK: %[[ADDR:.*]] = fir.box_addr %[[VAL_28]] : (!fir.class>>) -> !fir.heap> +// CHECK: %[[VAL_33:.*]] = fir.shape_shift %[[VAL_15]]#0, %[[VAL_15]]#1, %[[VAL_16]]#0, %[[VAL_16]]#1 : (index, index, index, index) -> !fir.shapeshift<2> +// CHECK: %[[VAL_34:.*]] = fir.embox %[[ADDR]](%[[VAL_33]]) source_box %[[ARG0]] : (!fir.heap>, !fir.shapeshift<2>, !fir.class>) -> !fir.class> // CHECK: %[[VAL_29:.*]] = fir.address_of(@{{_QQcl.*}}) : !fir.ref> -// CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_28]] : (!fir.class>>) -> !fir.box +// CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_34]] : (!fir.class>) -> !fir.box // CHECK: %[[VAL_31:.*]] = fir.convert %[[ARG0]] : (!fir.class>) -> !fir.box // CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_29]] : (!fir.ref>) -> !fir.ref // CHECK: fir.call @_FortranAShallowCopyDirect(%[[VAL_30]], %[[VAL_31]], %[[VAL_32]], %[[VAL_1]]) : (!fir.box, !fir.box, !fir.ref, i32) -> () -// CHECK: %[[VAL_33:.*]] = fir.shift %[[VAL_15]]#0, %[[VAL_16]]#0 : (index, index) -> !fir.shift<2> -// CHECK: %[[VAL_34:.*]] = fir.rebox %[[VAL_28]](%[[VAL_33]]) : (!fir.class>>, !fir.shift<2>) -> !fir.class> // CHECK: fir.result %[[VAL_34]] : !fir.class> // CHECK: } else { // CHECK: fir.result %[[ARG0]] : !fir.class> @@ -1057,13 +1050,14 @@ func.func @_QPtest7_stack(%arg0: !fir.class> {fir.bindc_nam // CHECK: %[[VAL_26:.*]] = fir.call @_FortranAAllocatableAllocate(%[[VAL_23]], %[[VAL_24]], %[[VAL_4]], %[[VAL_22]], %[[VAL_25]], %[[VAL_1]]) : (!fir.ref>, !fir.ref, i1, !fir.box, !fir.ref, i32) -> i32 // CHECK: %[[VAL_27:.*]] = fir.load %[[VAL_5]] : !fir.ref>>> // CHECK: %[[VAL_28:.*]] = fir.declare %[[VAL_27]] {uniq_name = ".repacked"} : (!fir.class>>) -> !fir.class>> +// CHECK: %[[ADDR:.*]] = fir.box_addr %[[VAL_28]] : (!fir.class>>) -> !fir.heap> +// CHECK: %[[VAL_33:.*]] = fir.shape_shift %[[VAL_15]]#0, %[[VAL_15]]#1, %[[VAL_16]]#0, %[[VAL_16]]#1 : (index, index, index, index) -> !fir.shapeshift<2> +// CHECK: %[[VAL_34:.*]] = fir.embox %[[ADDR]](%[[VAL_33]]) source_box %[[ARG0]] : (!fir.heap>, !fir.shapeshift<2>, !fir.class>) -> !fir.class> // CHECK: %[[VAL_29:.*]] = fir.address_of(@{{_QQcl.*}}) : !fir.ref> -// CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_28]] : (!fir.class>>) -> !fir.box +// CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_34]] : (!fir.class>) -> !fir.box // CHECK: %[[VAL_31:.*]] = fir.convert %[[ARG0]] : (!fir.class>) -> !fir.box // CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_29]] : (!fir.ref>) -> !fir.ref // CHECK: fir.call @_FortranAShallowCopyDirect(%[[VAL_30]], %[[VAL_31]], %[[VAL_32]], %[[VAL_1]]) : (!fir.box, !fir.box, !fir.ref, i32) -> () -// CHECK: %[[VAL_33:.*]] = fir.shift %[[VAL_15]]#0, %[[VAL_16]]#0 : (index, index) -> !fir.shift<2> -// CHECK: %[[VAL_34:.*]] = fir.rebox %[[VAL_28]](%[[VAL_33]]) : (!fir.class>>, !fir.shift<2>) -> !fir.class> // CHECK: fir.result %[[VAL_34]] : !fir.class> // CHECK: } else { // CHECK: fir.result %[[ARG0]] : !fir.class> diff --git a/flang/test/Transforms/tbaa-local-alloc-threshold.fir b/flang/test/Transforms/tbaa-local-alloc-threshold.fir new file mode 100644 index 0000000000000..27c19a6e23095 --- /dev/null +++ b/flang/test/Transforms/tbaa-local-alloc-threshold.fir @@ -0,0 +1,23 @@ +// Check that -local-alloc-tbaa-threshold option limits +// the attachment of TBAA tags to accesses of locally allocated entities. +// RUN: fir-opt --fir-add-alias-tags -local-alloc-tbaa-threshold=2 %s | FileCheck %s --check-prefixes=ALL,COUNT2 +// RUN: fir-opt --fir-add-alias-tags -local-alloc-tbaa-threshold=1 %s | FileCheck %s --check-prefixes=ALL,COUNT1 +// RUN: fir-opt --fir-add-alias-tags -local-alloc-tbaa-threshold=0 %s | FileCheck %s --check-prefixes=ALL,COUNT0 + +// ALL-LABEL: func.func @_QPtest() { +// COUNT2: fir.load{{.*}}{tbaa = +// COUNT2: fir.store{{.*}}{tbaa = +// COUNT1: fir.load{{.*}}{tbaa = +// COUNT1-NOT: fir.store{{.*}}{tbaa = +// COUNT0-NOT: fir.load{{.*}}{tbaa = +// COUNT0-NOT: fir.store{{.*}}{tbaa = +func.func @_QPtest() { + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFtestEx"} + %2 = fir.declare %1 {uniq_name = "_QFtestEx"} : (!fir.ref) -> !fir.ref + %3 = fir.alloca f32 {bindc_name = "y", uniq_name = "_QFtestEy"} + %4 = fir.declare %3 {uniq_name = "_QFtestEy"} : (!fir.ref) -> !fir.ref + %5 = fir.load %4 : !fir.ref + fir.store %5 to %2 : !fir.ref + return +} diff --git a/flang/unittests/Optimizer/Builder/CharacterTest.cpp b/flang/unittests/Optimizer/Builder/CharacterTest.cpp index 6d912b81d9541..d8d2da40ba9a6 100644 --- a/flang/unittests/Optimizer/Builder/CharacterTest.cpp +++ b/flang/unittests/Optimizer/Builder/CharacterTest.cpp @@ -29,7 +29,7 @@ struct CharacterTest : public testing::Test { moduleOp = builder.create(loc); builder.setInsertionPointToStart(moduleOp->getBody()); mlir::func::FuncOp func = builder.create( - loc, "func1", builder.getFunctionType(std::nullopt, std::nullopt)); + loc, "func1", builder.getFunctionType({}, {})); auto *entryBlock = func.addEntryBlock(); builder.setInsertionPointToStart(entryBlock); diff --git a/flang/unittests/Optimizer/Builder/ComplexTest.cpp b/flang/unittests/Optimizer/Builder/ComplexTest.cpp index 689af4642b0b6..d5f00c9b61108 100644 --- a/flang/unittests/Optimizer/Builder/ComplexTest.cpp +++ b/flang/unittests/Optimizer/Builder/ComplexTest.cpp @@ -25,7 +25,7 @@ struct ComplexTest : public testing::Test { moduleOp = builder.create(loc); builder.setInsertionPointToStart(moduleOp->getBody()); mlir::func::FuncOp func = builder.create( - loc, "func1", builder.getFunctionType(std::nullopt, std::nullopt)); + loc, "func1", builder.getFunctionType({}, {})); auto *entryBlock = func.addEntryBlock(); builder.setInsertionPointToStart(entryBlock); diff --git a/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp b/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp index 3e2af24c47b96..e4c21f6b65a36 100644 --- a/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp +++ b/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp @@ -29,7 +29,7 @@ struct FIRBuilderTest : public testing::Test { moduleOp = builder.create(loc); builder.setInsertionPointToStart(moduleOp->getBody()); mlir::func::FuncOp func = builder.create( - loc, "func1", builder.getFunctionType(std::nullopt, std::nullopt)); + loc, "func1", builder.getFunctionType({}, {})); auto *entryBlock = func.addEntryBlock(); builder.setInsertionPointToStart(entryBlock); @@ -176,8 +176,7 @@ TEST_F(FIRBuilderTest, getNamedFunction) { auto func2 = builder.getNamedFunction("func2"); EXPECT_EQ(nullptr, func2); auto loc = builder.getUnknownLoc(); - func2 = builder.createFunction( - loc, "func2", builder.getFunctionType(std::nullopt, std::nullopt)); + func2 = builder.createFunction(loc, "func2", builder.getFunctionType({}, {})); auto func2query = builder.getNamedFunction("func2"); EXPECT_EQ(func2, func2query); } diff --git a/flang/unittests/Optimizer/Builder/HLFIRToolsTest.cpp b/flang/unittests/Optimizer/Builder/HLFIRToolsTest.cpp index 29700d2d3dbff..a0785198b078d 100644 --- a/flang/unittests/Optimizer/Builder/HLFIRToolsTest.cpp +++ b/flang/unittests/Optimizer/Builder/HLFIRToolsTest.cpp @@ -28,7 +28,7 @@ struct HLFIRToolsTest : public testing::Test { moduleOp = builder.create(loc); builder.setInsertionPointToStart(moduleOp->getBody()); mlir::func::FuncOp func = builder.create( - loc, "func1", builder.getFunctionType(std::nullopt, std::nullopt)); + loc, "func1", builder.getFunctionType({}, {})); auto *entryBlock = func.addEntryBlock(); builder.setInsertionPointToStart(entryBlock); diff --git a/flang/unittests/Optimizer/Builder/Runtime/RuntimeCallTestBase.h b/flang/unittests/Optimizer/Builder/Runtime/RuntimeCallTestBase.h index 40abf567400b3..4ecec92f42dc2 100644 --- a/flang/unittests/Optimizer/Builder/Runtime/RuntimeCallTestBase.h +++ b/flang/unittests/Optimizer/Builder/Runtime/RuntimeCallTestBase.h @@ -26,9 +26,8 @@ struct RuntimeCallTest : public testing::Test { // Set the insertion point in the function entry block. moduleOp = builder.create(loc); builder.setInsertionPointToStart(moduleOp->getBody()); - mlir::func::FuncOp func = - builder.create(loc, "runtime_unit_tests_func", - builder.getFunctionType(std::nullopt, std::nullopt)); + mlir::func::FuncOp func = builder.create( + loc, "runtime_unit_tests_func", builder.getFunctionType({}, {})); auto *entryBlock = func.addEntryBlock(); builder.setInsertionPointToStart(entryBlock); diff --git a/flang/unittests/Optimizer/FortranVariableTest.cpp b/flang/unittests/Optimizer/FortranVariableTest.cpp index 30c23b63b4d56..59808779aa6ef 100644 --- a/flang/unittests/Optimizer/FortranVariableTest.cpp +++ b/flang/unittests/Optimizer/FortranVariableTest.cpp @@ -21,9 +21,8 @@ struct FortranVariableTest : public testing::Test { // Set the insertion point in the function entry block. moduleOp = builder->create(loc); builder->setInsertionPointToStart(moduleOp->getBody()); - mlir::func::FuncOp func = - builder->create(loc, "fortran_variable_tests", - builder->getFunctionType(std::nullopt, std::nullopt)); + mlir::func::FuncOp func = builder->create( + loc, "fortran_variable_tests", builder->getFunctionType({}, {})); auto *entryBlock = func.addEntryBlock(); builder->setInsertionPointToStart(entryBlock); } @@ -49,7 +48,7 @@ TEST_F(FortranVariableTest, SimpleScalar) { mlir::Value addr = builder->create(loc, eleType); auto name = mlir::StringAttr::get(&context, "x"); auto declare = builder->create(loc, addr.getType(), addr, - /*shape=*/mlir::Value{}, /*typeParams=*/std::nullopt, + /*shape=*/mlir::Value{}, /*typeParams=*/mlir::ValueRange{}, /*dummy_scope=*/nullptr, name, /*fortran_attrs=*/fir::FortranVariableFlagsAttr{}, /*data_attr=*/cuf::DataAttributeAttr{}); @@ -103,11 +102,11 @@ TEST_F(FortranVariableTest, SimpleArray) { extents.size(), fir::SequenceType::getUnknownExtent()); mlir::Type seqTy = fir::SequenceType::get(typeShape, eleType); mlir::Value addr = builder->create( - loc, seqTy, /*pinned=*/false, /*typeParams=*/std::nullopt, extents); + loc, seqTy, /*pinned=*/false, /*typeParams=*/mlir::ValueRange{}, extents); mlir::Value shape = createShape(extents); auto name = mlir::StringAttr::get(&context, "x"); auto declare = builder->create(loc, addr.getType(), addr, - shape, /*typeParams*/ std::nullopt, /*dummy_scope=*/nullptr, name, + shape, /*typeParams=*/mlir::ValueRange{}, /*dummy_scope=*/nullptr, name, /*fortran_attrs=*/fir::FortranVariableFlagsAttr{}, /*data_attr=*/cuf::DataAttributeAttr{}); diff --git a/libc/benchmarks/gpu/LibcGpuBenchmark.cpp b/libc/benchmarks/gpu/LibcGpuBenchmark.cpp index 920c5b206b0fe..57ff5b9fdb846 100644 --- a/libc/benchmarks/gpu/LibcGpuBenchmark.cpp +++ b/libc/benchmarks/gpu/LibcGpuBenchmark.cpp @@ -7,9 +7,9 @@ #include "src/__support/GPU/utils.h" #include "src/__support/fixedvector.h" #include "src/__support/macros/config.h" +#include "src/__support/time/gpu/time_utils.h" #include "src/stdio/printf.h" #include "src/stdlib/srand.h" -#include "src/time/gpu/time_utils.h" namespace LIBC_NAMESPACE_DECL { namespace benchmarks { diff --git a/libc/benchmarks/gpu/src/math/atan2_benchmark.cpp b/libc/benchmarks/gpu/src/math/atan2_benchmark.cpp index 3bb5b0cc6788c..1f91a9a35c373 100644 --- a/libc/benchmarks/gpu/src/math/atan2_benchmark.cpp +++ b/libc/benchmarks/gpu/src/math/atan2_benchmark.cpp @@ -3,12 +3,8 @@ #include "src/math/atan2.h" #include "src/stdlib/rand.h" -#ifdef NVPTX_MATH_FOUND -#include "src/math/nvptx/declarations.h" -#endif - -#ifdef AMDGPU_MATH_FOUND -#include "src/math/amdgpu/declarations.h" +#if defined(NVPTX_MATH_FOUND) || defined(AMDGPU_MATH_FOUND) +#include "platform.h" #endif #define BM_TWO_RANDOM_INPUT(T, Func, MIN_EXP, MAX_EXP, N) \ @@ -33,15 +29,15 @@ BENCH(double, Atan2TwoPow30, LIBC_NAMESPACE::atan2, 0, 30); BENCH(double, Atan2Large, LIBC_NAMESPACE::atan2, 30, 1000); #ifdef NVPTX_MATH_FOUND -BENCH(double, NvAtan2, LIBC_NAMESPACE::__nv_atan2, -1023, 1023); -BENCH(double, NvAtan2TwoPi, LIBC_NAMESPACE::__nv_atan2, -10, 3); -BENCH(double, NvAtan2TwoPow30, LIBC_NAMESPACE::__nv_atan2, 0, 30); -BENCH(double, NvAtan2Large, LIBC_NAMESPACE::__nv_atan2, 30, 1000); +BENCH(double, NvAtan2, __nv_atan2, -1023, 1023); +BENCH(double, NvAtan2TwoPi, __nv_atan2, -10, 3); +BENCH(double, NvAtan2TwoPow30, __nv_atan2, 0, 30); +BENCH(double, NvAtan2Large, __nv_atan2, 30, 1000); #endif #ifdef AMDGPU_MATH_FOUND -BENCH(double, AmdAtan2, LIBC_NAMESPACE::__ocml_atan2_f64, -1023, 1023); -BENCH(double, AmdAtan2TwoPi, LIBC_NAMESPACE::__ocml_atan2_f64, -10, 3); -BENCH(double, AmdAtan2TwoPow30, LIBC_NAMESPACE::__ocml_atan2_f64, 0, 30); -BENCH(double, AmdAtan2Large, LIBC_NAMESPACE::__ocml_atan2_f64, 30, 1000); +BENCH(double, AmdAtan2, __ocml_atan2_f64, -1023, 1023); +BENCH(double, AmdAtan2TwoPi, __ocml_atan2_f64, -10, 3); +BENCH(double, AmdAtan2TwoPow30, __ocml_atan2_f64, 0, 30); +BENCH(double, AmdAtan2Large, __ocml_atan2_f64, 30, 1000); #endif diff --git a/libc/benchmarks/gpu/src/math/platform.h b/libc/benchmarks/gpu/src/math/platform.h new file mode 100644 index 0000000000000..bb7825d38bd42 --- /dev/null +++ b/libc/benchmarks/gpu/src/math/platform.h @@ -0,0 +1,57 @@ +//===-- AMDGPU specific platform definitions for math support -------------===// +// +// 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_LIBC_SRC_MATH_AMDGPU_PLATFORM_H +#define LLVM_LIBC_SRC_MATH_AMDGPU_PLATFORM_H +#include "src/__support/macros/attributes.h" +#include "src/__support/macros/config.h" +#include + +namespace LIBC_NAMESPACE_DECL { + +#ifdef LIBC_TARGET_ARCH_IS_AMDGPU +// The ROCm device library uses control globals to alter codegen for the +// different targets. To avoid needing to link them in manually we simply +// define them here. +extern "C" { +extern const LIBC_INLINE_VAR uint8_t __oclc_unsafe_math_opt = 0; +extern const LIBC_INLINE_VAR uint8_t __oclc_daz_opt = 0; +extern const LIBC_INLINE_VAR uint8_t __oclc_correctly_rounded_sqrt32 = 1; +extern const LIBC_INLINE_VAR uint8_t __oclc_finite_only_opt = 0; +extern const LIBC_INLINE_VAR uint32_t __oclc_ISA_version = 9000; +} + +// These aliases cause clang to emit the control constants with ODR linkage. +// This allows us to link against the symbols without preventing them from being +// optimized out or causing symbol collisions. +[[gnu::alias("__oclc_unsafe_math_opt")]] const uint8_t __oclc_unsafe_math_opt__; +[[gnu::alias("__oclc_daz_opt")]] const uint8_t __oclc_daz_opt__; +[[gnu::alias("__oclc_correctly_rounded_sqrt32")]] const uint8_t + __oclc_correctly_rounded_sqrt32__; +[[gnu::alias("__oclc_finite_only_opt")]] const uint8_t __oclc_finite_only_opt__; +[[gnu::alias("__oclc_ISA_version")]] const uint32_t __oclc_ISA_version__; +#endif +} // namespace LIBC_NAMESPACE_DECL + +// Forward declarations for the vendor math libraries. +extern "C" { +#ifdef AMDGPU_MATH_FOUND +double __ocml_sin_f64(double); +float __ocml_sin_f32(float); +double __ocml_atan2_f64(double, double); +float __ocml_atan2_f32(float, float); +#endif + +#ifdef NVPTX_MATH_FOUND +double __nv_sin(double); +float __nv_sinf(float); +double __nv_atan2(double, double); +float __nv_atan2f(float, float); +#endif +} + +#endif // LLVM_LIBC_SRC_MATH_AMDGPU_PLATFORM_H diff --git a/libc/benchmarks/gpu/src/math/sin_benchmark.cpp b/libc/benchmarks/gpu/src/math/sin_benchmark.cpp index bf09e6e462172..a759db2e9d33f 100644 --- a/libc/benchmarks/gpu/src/math/sin_benchmark.cpp +++ b/libc/benchmarks/gpu/src/math/sin_benchmark.cpp @@ -8,12 +8,8 @@ #include "src/math/sinf.h" #include "src/stdlib/rand.h" -#ifdef NVPTX_MATH_FOUND -#include "src/math/nvptx/declarations.h" -#endif - -#ifdef AMDGPU_MATH_FOUND -#include "src/math/amdgpu/declarations.h" +#if defined(NVPTX_MATH_FOUND) || defined(AMDGPU_MATH_FOUND) +#include "platform.h" #endif // BENCHMARK() expects a function that with no parameters that returns a @@ -42,17 +38,17 @@ BENCH(double, SinTwoPow30, LIBC_NAMESPACE::sin, 0, 30); BENCH(double, SinVeryLarge, LIBC_NAMESPACE::sin, 30, 1000); #ifdef NVPTX_MATH_FOUND -BENCH(double, NvSin, LIBC_NAMESPACE::__nv_sin, -1023, 1023); -BENCH(double, NvSinTwoPi, LIBC_NAMESPACE::__nv_sin, -10, 3); -BENCH(double, NvSinTwoPow30, LIBC_NAMESPACE::__nv_sin, 0, 30); -BENCH(double, NvSinVeryLarge, LIBC_NAMESPACE::__nv_sin, 30, 1000); +BENCH(double, NvSin, __nv_sin, -1023, 1023); +BENCH(double, NvSinTwoPi, __nv_sin, -10, 3); +BENCH(double, NvSinTwoPow30, __nv_sin, 0, 30); +BENCH(double, NvSinVeryLarge, __nv_sin, 30, 1000); #endif #ifdef AMDGPU_MATH_FOUND -BENCH(double, AmdSin, LIBC_NAMESPACE::__ocml_sin_f64, -1023, 1023); -BENCH(double, AmdSinTwoPi, LIBC_NAMESPACE::__ocml_sin_f64, -10, 3); -BENCH(double, AmdSinTwoPow30, LIBC_NAMESPACE::__ocml_sin_f64, 0, 30); -BENCH(double, AmdSinVeryLarge, LIBC_NAMESPACE::__ocml_sin_f64, 30, 1000); +BENCH(double, AmdSin, __ocml_sin_f64, -1023, 1023); +BENCH(double, AmdSinTwoPi, __ocml_sin_f64, -10, 3); +BENCH(double, AmdSinTwoPow30, __ocml_sin_f64, 0, 30); +BENCH(double, AmdSinVeryLarge, __ocml_sin_f64, 30, 1000); #endif BENCH(float, Sinf, LIBC_NAMESPACE::sinf, -127, 128); @@ -61,15 +57,15 @@ BENCH(float, SinfTwoPow30, LIBC_NAMESPACE::sinf, 0, 30); BENCH(float, SinfVeryLarge, LIBC_NAMESPACE::sinf, 30, 120); #ifdef NVPTX_MATH_FOUND -BENCH(float, NvSinf, LIBC_NAMESPACE::__nv_sinf, -127, 128); -BENCH(float, NvSinfTwoPi, LIBC_NAMESPACE::__nv_sinf, -10, 3); -BENCH(float, NvSinfTwoPow30, LIBC_NAMESPACE::__nv_sinf, 0, 30); -BENCH(float, NvSinfVeryLarge, LIBC_NAMESPACE::__nv_sinf, 30, 120); +BENCH(float, NvSinf, __nv_sinf, -127, 128); +BENCH(float, NvSinfTwoPi, __nv_sinf, -10, 3); +BENCH(float, NvSinfTwoPow30, __nv_sinf, 0, 30); +BENCH(float, NvSinfVeryLarge, __nv_sinf, 30, 120); #endif #ifdef AMDGPU_MATH_FOUND -BENCH(float, AmdSinf, LIBC_NAMESPACE::__ocml_sin_f32, -127, 128); -BENCH(float, AmdSinfTwoPi, LIBC_NAMESPACE::__ocml_sin_f32, -10, 3); -BENCH(float, AmdSinfTwoPow30, LIBC_NAMESPACE::__ocml_sin_f32, 0, 30); -BENCH(float, AmdSinfVeryLarge, LIBC_NAMESPACE::__ocml_sin_f32, 30, 120); +BENCH(float, AmdSinf, __ocml_sin_f32, -127, 128); +BENCH(float, AmdSinfTwoPi, __ocml_sin_f32, -10, 3); +BENCH(float, AmdSinfTwoPow30, __ocml_sin_f32, 0, 30); +BENCH(float, AmdSinfVeryLarge, __ocml_sin_f32, 30, 120); #endif diff --git a/libc/benchmarks/gpu/timing/amdgpu/timing.h b/libc/benchmarks/gpu/timing/amdgpu/timing.h index 4cf7e9838add3..0f2c04c07c921 100644 --- a/libc/benchmarks/gpu/timing/amdgpu/timing.h +++ b/libc/benchmarks/gpu/timing/amdgpu/timing.h @@ -10,6 +10,7 @@ #define LLVM_LIBC_UTILS_GPU_TIMING_AMDGPU #include "src/__support/CPP/array.h" +#include "src/__support/CPP/atomic.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/GPU/utils.h" #include "src/__support/common.h" @@ -24,7 +25,7 @@ namespace LIBC_NAMESPACE_DECL { // allows us to substract the constant-time overhead from the latency to // obtain a true result. This can vary with system load. [[gnu::noinline]] static LIBC_INLINE uint64_t overhead() { - gpu::memory_fence(); + cpp::atomic_thread_fence(cpp::MemoryOrder::ACQ_REL); uint64_t start = gpu::processor_clock(); uint32_t result = 0.0; asm("v_or_b32 %[v_reg], 0, %[v_reg]\n" ::[v_reg] "v"(result)); @@ -44,13 +45,13 @@ template T arg = storage; // The AMDGPU architecture needs to wait on pending results. - gpu::memory_fence(); + cpp::atomic_thread_fence(cpp::MemoryOrder::ACQ_REL); // Get the current timestamp from the clock. uint64_t start = gpu::processor_clock(); // This forces the compiler to load the input argument and run the clock // cycle counter before the profiling region. - asm("" ::"s"(start)); + asm("" : "+v"(arg) : "s"(start)); // Run the function under test and return its value. auto result = f(arg); @@ -71,7 +72,7 @@ template // ordering. uint64_t stop = gpu::processor_clock(); asm("" ::"s"(stop)); - gpu::memory_fence(); + cpp::atomic_thread_fence(cpp::MemoryOrder::ACQ_REL); // Return the time elapsed. return stop - start; @@ -84,7 +85,7 @@ template T1 arg1 = storage1; T2 arg2 = storage2; - gpu::memory_fence(); + cpp::atomic_thread_fence(cpp::MemoryOrder::ACQ_REL); uint64_t start = gpu::processor_clock(); asm("" ::"s"(start)); @@ -100,7 +101,7 @@ template uint64_t stop = gpu::processor_clock(); asm("" ::"s"(stop)); - gpu::memory_fence(); + cpp::atomic_thread_fence(cpp::MemoryOrder::ACQ_REL); return stop - start; } @@ -111,7 +112,7 @@ template throughput(F f, const cpp::array &inputs) { asm("" ::"v"(&inputs)); - gpu::memory_fence(); + cpp::atomic_thread_fence(cpp::MemoryOrder::ACQ_REL); uint64_t start = gpu::processor_clock(); asm("" ::"s"(start)); @@ -124,7 +125,7 @@ throughput(F f, const cpp::array &inputs) { uint64_t stop = gpu::processor_clock(); asm("" ::"s"(stop)); - gpu::memory_fence(); + cpp::atomic_thread_fence(cpp::MemoryOrder::ACQ_REL); // Return the time elapsed. return stop - start; @@ -136,7 +137,7 @@ template F f, const cpp::array &inputs1, const cpp::array &inputs2) { asm("" ::"v"(&inputs1), "v"(&inputs2)); - gpu::memory_fence(); + cpp::atomic_thread_fence(cpp::MemoryOrder::ACQ_REL); uint64_t start = gpu::processor_clock(); asm("" ::"s"(start)); @@ -149,7 +150,7 @@ template uint64_t stop = gpu::processor_clock(); asm("" ::"s"(stop)); - gpu::memory_fence(); + cpp::atomic_thread_fence(cpp::MemoryOrder::ACQ_REL); // Return the time elapsed. return stop - start; diff --git a/libc/benchmarks/gpu/timing/nvptx/timing.h b/libc/benchmarks/gpu/timing/nvptx/timing.h index ece7d9a6c5396..3ed97645ddc93 100644 --- a/libc/benchmarks/gpu/timing/nvptx/timing.h +++ b/libc/benchmarks/gpu/timing/nvptx/timing.h @@ -10,6 +10,7 @@ #define LLVM_LIBC_UTILS_GPU_TIMING_NVPTX #include "src/__support/CPP/array.h" +#include "src/__support/CPP/atomic.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/GPU/utils.h" #include "src/__support/common.h" @@ -46,7 +47,7 @@ template T arg = storage; // Get the current timestamp from the clock. - gpu::memory_fence(); + cpp::atomic_thread_fence(cpp::MemoryOrder::ACQ_REL); uint64_t start = gpu::processor_clock(); // This forces the compiler to load the input argument and run the clock cycle @@ -63,7 +64,7 @@ template // Obtain the current timestamp after running the calculation and force // ordering. uint64_t stop = gpu::processor_clock(); - gpu::memory_fence(); + cpp::atomic_thread_fence(cpp::MemoryOrder::ACQ_REL); asm("" ::"r"(stop)); volatile T output = result; @@ -78,7 +79,7 @@ static LIBC_INLINE uint64_t latency(F f, T1 t1, T2 t2) { T1 arg = storage; T2 arg2 = storage2; - gpu::memory_fence(); + cpp::atomic_thread_fence(cpp::MemoryOrder::ACQ_REL); uint64_t start = gpu::processor_clock(); asm("" ::"llr"(start)); @@ -88,7 +89,7 @@ static LIBC_INLINE uint64_t latency(F f, T1 t1, T2 t2) { asm("or.b32 %[v_reg], %[v_reg], 0;" ::[v_reg] "r"(result)); uint64_t stop = gpu::processor_clock(); - gpu::memory_fence(); + cpp::atomic_thread_fence(cpp::MemoryOrder::ACQ_REL); asm("" ::"r"(stop)); volatile auto output = result; @@ -101,7 +102,7 @@ template throughput(F f, const cpp::array &inputs) { asm("" ::"r"(&inputs)); - gpu::memory_fence(); + cpp::atomic_thread_fence(cpp::MemoryOrder::ACQ_REL); uint64_t start = gpu::processor_clock(); asm("" ::"llr"(start)); @@ -114,7 +115,7 @@ throughput(F f, const cpp::array &inputs) { } uint64_t stop = gpu::processor_clock(); - gpu::memory_fence(); + cpp::atomic_thread_fence(cpp::MemoryOrder::ACQ_REL); asm("" ::"r"(stop)); volatile auto output = result; @@ -128,7 +129,7 @@ template F f, const cpp::array &inputs1, const cpp::array &inputs2) { asm("" ::"r"(&inputs1), "r"(&inputs2)); - gpu::memory_fence(); + cpp::atomic_thread_fence(cpp::MemoryOrder::ACQ_REL); uint64_t start = gpu::processor_clock(); asm("" ::"llr"(start)); @@ -140,7 +141,7 @@ template } uint64_t stop = gpu::processor_clock(); - gpu::memory_fence(); + cpp::atomic_thread_fence(cpp::MemoryOrder::ACQ_REL); asm("" ::"r"(stop)); volatile auto output = result; diff --git a/libc/cmake/modules/LLVMLibCArchitectures.cmake b/libc/cmake/modules/LLVMLibCArchitectures.cmake index c94a407d974df..d4103f8a5a23f 100644 --- a/libc/cmake/modules/LLVMLibCArchitectures.cmake +++ b/libc/cmake/modules/LLVMLibCArchitectures.cmake @@ -153,9 +153,11 @@ elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "x86_64") elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "i386") set(LIBC_TARGET_ARCHITECTURE_IS_X86 TRUE) elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "riscv64") + set(LIBC_TARGET_ARCHITECTURE_IS_ANY_RISCV TRUE) set(LIBC_TARGET_ARCHITECTURE_IS_RISCV64 TRUE) set(LIBC_TARGET_ARCHITECTURE "riscv") elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "riscv32") + set(LIBC_TARGET_ARCHITECTURE_IS_ANY_RISCV TRUE) set(LIBC_TARGET_ARCHITECTURE_IS_RISCV32 TRUE) set(LIBC_TARGET_ARCHITECTURE "riscv") elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "amdgpu") diff --git a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake index 82d06e2b9eb55..2478fde64d430 100644 --- a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake +++ b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake @@ -13,7 +13,7 @@ endif() function(_get_compile_options_from_flags output_var) set(compile_options "") - if(LIBC_TARGET_ARCHITECTURE_IS_RISCV64 OR(LIBC_CPU_FEATURES MATCHES "FMA")) + if(LIBC_CPU_FEATURES MATCHES "FMA") check_flag(ADD_FMA_FLAG ${FMA_OPT_FLAG} ${ARGN}) endif() check_flag(ADD_ROUND_OPT_FLAG ${ROUND_OPT_FLAG} ${ARGN}) @@ -25,8 +25,6 @@ function(_get_compile_options_from_flags output_var) if(LIBC_TARGET_ARCHITECTURE_IS_X86_64) list(APPEND compile_options "-mavx2") list(APPEND compile_options "-mfma") - elseif(LIBC_TARGET_ARCHITECTURE_IS_RISCV64) - list(APPEND compile_options "-D__LIBC_RISCV_USE_FMA") endif() # For clang, we will build the math functions with `-fno-math-errno` so that # __builtin_fma* will generate the fused-mutliply-add instructions. We diff --git a/libc/cmake/modules/LLVMLibCFlagRules.cmake b/libc/cmake/modules/LLVMLibCFlagRules.cmake index 7d5e73c2f1214..4bbd21ab569dc 100644 --- a/libc/cmake/modules/LLVMLibCFlagRules.cmake +++ b/libc/cmake/modules/LLVMLibCFlagRules.cmake @@ -270,7 +270,7 @@ set(MISC_MATH_BASIC_OPS_OPT_FLAG "MISC_MATH_BASIC_OPS_OPT") # Skip FMA_OPT flag for targets that don't support fma. if(NOT DEFINED SKIP_FLAG_EXPANSION_FMA_OPT) if(NOT((LIBC_TARGET_ARCHITECTURE_IS_X86_64 AND (LIBC_CPU_FEATURES MATCHES "FMA")) OR - LIBC_TARGET_ARCHITECTURE_IS_RISCV64)) + LIBC_TARGET_ARCHITECTURE_IS_ANY_RISCV)) set(SKIP_FLAG_EXPANSION_FMA_OPT TRUE) endif() endif() diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake index e210992c5111a..267c32e956945 100644 --- a/libc/cmake/modules/LLVMLibCTestRules.cmake +++ b/libc/cmake/modules/LLVMLibCTestRules.cmake @@ -71,6 +71,7 @@ endfunction() function(_get_hermetic_test_compile_options output_var) _get_common_test_compile_options(compile_options "" "") + list(APPEND compile_options "-DLIBC_TEST=HERMETIC") # null check tests are death tests, remove from hermetic tests for now. if(LIBC_ADD_NULL_CHECKS) @@ -232,6 +233,7 @@ function(create_libc_unittest fq_target_name) _get_common_test_compile_options(compile_options "${LIBC_UNITTEST_C_TEST}" "${LIBC_UNITTEST_FLAGS}") + list(APPEND compile_options "-DLIBC_TEST=UNIT") # TODO: Ideally we would have a separate function for link options. set(link_options ${compile_options} @@ -571,6 +573,8 @@ function(add_integration_test test_name) target_compile_options(${fq_build_target_name} PRIVATE ${compile_options} ${INTEGRATION_TEST_COMPILE_OPTIONS}) + set(compiler_runtime "") + if(LIBC_TARGET_ARCHITECTURE_IS_AMDGPU) target_link_options(${fq_build_target_name} PRIVATE ${LIBC_COMPILE_OPTIONS_DEFAULT} ${INTEGRATION_TEST_COMPILE_OPTIONS} @@ -599,17 +603,19 @@ function(add_integration_test test_name) set(link_options -nolibc -nostartfiles - -static + -nostdlib ${LIBC_LINK_OPTIONS_DEFAULT} ${LIBC_TEST_LINK_OPTIONS_DEFAULT} ) target_link_options(${fq_build_target_name} PRIVATE ${link_options}) + list(APPEND compiler_runtime ${LIBGCC_S_LOCATION}) endif() target_link_libraries( ${fq_build_target_name} - ${fq_target_name}.__libc__ libc.startup.${LIBC_TARGET_OS}.crt1 libc.test.IntegrationTest.test + ${fq_target_name}.__libc__ + ${compiler_runtime} ) add_dependencies(${fq_build_target_name} libc.test.IntegrationTest.test @@ -770,6 +776,7 @@ function(add_libc_hermetic test_name) ${HERMETIC_TEST_COMPILE_OPTIONS}) set(link_libraries "") + set(compiler_runtime "") foreach(lib IN LISTS HERMETIC_TEST_LINK_LIBRARIES) if(TARGET ${lib}.hermetic) list(APPEND link_libraries ${lib}.hermetic) @@ -807,12 +814,12 @@ function(add_libc_hermetic test_name) set(link_options -nolibc -nostartfiles - -static + -nostdlib ${LIBC_LINK_OPTIONS_DEFAULT} ${LIBC_TEST_LINK_OPTIONS_DEFAULT} ) target_link_options(${fq_build_target_name} PRIVATE ${link_options}) - list(APPEND link_libraries ${LIBGCC_S_LOCATION}) + list(APPEND compiler_runtime ${LIBGCC_S_LOCATION}) endif() target_link_libraries( ${fq_build_target_name} @@ -820,7 +827,9 @@ function(add_libc_hermetic test_name) libc.startup.${LIBC_TARGET_OS}.crt1 ${link_libraries} LibcHermeticTestSupport.hermetic - ${fq_target_name}.__libc__) + ${fq_target_name}.__libc__ + ${compiler_runtime} + ) add_dependencies(${fq_build_target_name} LibcTest.hermetic libc.test.UnitTest.ErrnoSetterMatcher diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt index de7549c57ff44..80cd15eebc91f 100644 --- a/libc/config/baremetal/arm/entrypoints.txt +++ b/libc/config/baremetal/arm/entrypoints.txt @@ -278,6 +278,9 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.wchar.wcslen libc.src.wchar.wctob + # wctype.h entrypoints + libc.src.wctype.iswalpha + # internal entrypoints libc.startup.baremetal.init libc.startup.baremetal.fini diff --git a/libc/config/baremetal/arm/headers.txt b/libc/config/baremetal/arm/headers.txt index 5666ef7e0012d..1f64afebdaaa7 100644 --- a/libc/config/baremetal/arm/headers.txt +++ b/libc/config/baremetal/arm/headers.txt @@ -23,4 +23,5 @@ set(TARGET_PUBLIC_HEADERS libc.include.time libc.include.uchar libc.include.wchar + libc.include.wctype ) diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt index 7e8c186d52469..c9f8118f6e800 100644 --- a/libc/config/baremetal/riscv/entrypoints.txt +++ b/libc/config/baremetal/riscv/entrypoints.txt @@ -278,6 +278,9 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.wchar.wcslen libc.src.wchar.wctob + # wctype.h entrypoints + libc.src.wctype.iswalpha + # internal entrypoints libc.startup.baremetal.init libc.startup.baremetal.fini diff --git a/libc/config/baremetal/riscv/headers.txt b/libc/config/baremetal/riscv/headers.txt index 5666ef7e0012d..1f64afebdaaa7 100644 --- a/libc/config/baremetal/riscv/headers.txt +++ b/libc/config/baremetal/riscv/headers.txt @@ -23,4 +23,5 @@ set(TARGET_PUBLIC_HEADERS libc.include.time libc.include.uchar libc.include.wchar + libc.include.wctype ) diff --git a/libc/config/darwin/aarch64/entrypoints.txt b/libc/config/darwin/aarch64/entrypoints.txt index 4674a9309115b..3bfdcdbee555e 100644 --- a/libc/config/darwin/aarch64/entrypoints.txt +++ b/libc/config/darwin/aarch64/entrypoints.txt @@ -99,6 +99,9 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdlib.calloc libc.src.stdlib.realloc libc.src.stdlib.free + + # wctype.h entrypoints + libc.src.wctype.iswalpha ) if(LLVM_LIBC_FULL_BUILD) diff --git a/libc/config/darwin/aarch64/headers.txt b/libc/config/darwin/aarch64/headers.txt index 8f3d6029c9b6a..55a112c0c3ad3 100644 --- a/libc/config/darwin/aarch64/headers.txt +++ b/libc/config/darwin/aarch64/headers.txt @@ -11,4 +11,5 @@ set(TARGET_PUBLIC_HEADERS libc.include.stdlib libc.include.string libc.include.strings + libc.include.wctype ) diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index cff5b7f8312d6..b2abebee017d8 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -363,6 +363,9 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.wchar.wcslen libc.src.wchar.wctob + # wctype.h entrypoints + libc.src.wctype.iswalpha + # sys/uio.h entrypoints libc.src.sys.uio.writev libc.src.sys.uio.readv diff --git a/libc/config/linux/aarch64/headers.txt b/libc/config/linux/aarch64/headers.txt index 01b0bf36498ce..6d3bc9188583b 100644 --- a/libc/config/linux/aarch64/headers.txt +++ b/libc/config/linux/aarch64/headers.txt @@ -57,4 +57,5 @@ set(TARGET_PUBLIC_HEADERS libc.include.uchar libc.include.unistd libc.include.wchar + libc.include.wctype ) diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt index a1203cc4991af..5865dc93a9aef 100644 --- a/libc/config/linux/arm/entrypoints.txt +++ b/libc/config/linux/arm/entrypoints.txt @@ -191,6 +191,9 @@ set(TARGET_LIBC_ENTRYPOINTS # sys/time.h entrypoints libc.src.sys.time.setitimer libc.src.sys.time.getitimer + + # wctype.h entrypoints + libc.src.wctype.iswalpha ) if(LLVM_LIBC_FULL_BUILD) diff --git a/libc/config/linux/arm/headers.txt b/libc/config/linux/arm/headers.txt index 9aabac5dea33c..14c730e2b77b1 100644 --- a/libc/config/linux/arm/headers.txt +++ b/libc/config/linux/arm/headers.txt @@ -17,6 +17,7 @@ set(TARGET_PUBLIC_HEADERS libc.include.strings libc.include.uchar libc.include.wchar + libc.include.wctype # Disabled due to epoll_wait syscalls not being available on this platform. # libc.include.sys_epoll diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index 14361f5b6beff..79077a5e66ef5 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -368,6 +368,9 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.wchar.wcslen libc.src.wchar.wctob + # wctype.h entrypoints + libc.src.wctype.iswalpha + # sys/uio.h entrypoints libc.src.sys.uio.writev libc.src.sys.uio.readv diff --git a/libc/config/linux/riscv/headers.txt b/libc/config/linux/riscv/headers.txt index 01b0bf36498ce..6d3bc9188583b 100644 --- a/libc/config/linux/riscv/headers.txt +++ b/libc/config/linux/riscv/headers.txt @@ -57,4 +57,5 @@ set(TARGET_PUBLIC_HEADERS libc.include.uchar libc.include.unistd libc.include.wchar + libc.include.wctype ) diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 9223911f04a93..381359cec6f1d 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -396,6 +396,8 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.wchar.wcstoul libc.src.wchar.wcstoull + # wctype.h entrypoints + libc.src.wctype.iswalpha # sys/uio.h entrypoints libc.src.sys.uio.writev diff --git a/libc/config/linux/x86_64/headers.txt b/libc/config/linux/x86_64/headers.txt index 01b0bf36498ce..6d3bc9188583b 100644 --- a/libc/config/linux/x86_64/headers.txt +++ b/libc/config/linux/x86_64/headers.txt @@ -57,4 +57,5 @@ set(TARGET_PUBLIC_HEADERS libc.include.uchar libc.include.unistd libc.include.wchar + libc.include.wctype ) diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt index 8898fd74c302f..18027298acc18 100644 --- a/libc/config/windows/entrypoints.txt +++ b/libc/config/windows/entrypoints.txt @@ -105,6 +105,9 @@ set(TARGET_LIBC_ENTRYPOINTS # unistd.h entrypoints libc.src.unistd.getentropy + + # wctype.h entrypoints + libc.src.wctype.iswalpha ) set(TARGET_LIBM_ENTRYPOINTS diff --git a/libc/config/windows/headers.txt b/libc/config/windows/headers.txt index 6d9aae9276924..d4a0947d867bb 100644 --- a/libc/config/windows/headers.txt +++ b/libc/config/windows/headers.txt @@ -7,4 +7,5 @@ set(TARGET_PUBLIC_HEADERS libc.include.fenv libc.include.math libc.include.unistd + libc.include.wctype ) diff --git a/libc/fuzzing/math/CMakeLists.txt b/libc/fuzzing/math/CMakeLists.txt index c1a93058764b3..be63fe4b65aea 100644 --- a/libc/fuzzing/math/CMakeLists.txt +++ b/libc/fuzzing/math/CMakeLists.txt @@ -196,3 +196,12 @@ add_libc_fuzzer( DEPENDS libc.src.__support.FPUtil.generic.sqrt ) + +add_libc_fuzzer( + cbrt_fuzz + NEED_MPFR + SRCS + cbrt_fuzz.cpp + DEPENDS + libc.src.math.cbrt +) diff --git a/libc/fuzzing/math/acos_fuzz.cpp b/libc/fuzzing/math/acos_fuzz.cpp index d2b5456026839..48fb4eacc3a79 100644 --- a/libc/fuzzing/math/acos_fuzz.cpp +++ b/libc/fuzzing/math/acos_fuzz.cpp @@ -12,26 +12,40 @@ #include "src/math/acos.h" #include "utils/MPFRWrapper/mpfr_inc.h" +#include +#include +#include #include -extern "C" int LLVMFuzzerTestOneInput(double x) { - // remove NaN and inf and values outside accepted range - if (isnan(x) || isinf(x) || x > 1 || x < -1) - return 0; - // signed zeros already tested in unit tests - if (signbit(x) && x == 0.0) - return 0; +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { mpfr_t input; mpfr_init2(input, 53); - mpfr_set_d(input, x, MPFR_RNDN); - int output = mpfr_acos(input, input, MPFR_RNDN); - mpfr_subnormalize(input, output, MPFR_RNDN); - double to_compare = mpfr_get_d(input, MPFR_RNDN); + for (size_t i = 0; i < size / sizeof(double); ++i) { + double x; + std::memcpy(&x, data, sizeof(double)); + data += sizeof(double); + // remove NaN and inf and values outside accepted range + if (isnan(x) || isinf(x) || x > 1 || x < -1) + continue; - double result = LIBC_NAMESPACE::acos(x); + // signed zeros already tested in unit tests + if (signbit(x) && x == 0.0) + continue; - if (result != to_compare) - __builtin_trap(); + mpfr_set_d(input, x, MPFR_RNDN); + int output = mpfr_acos(input, input, MPFR_RNDN); + mpfr_subnormalize(input, output, MPFR_RNDN); + double to_compare = mpfr_get_d(input, MPFR_RNDN); + + double result = LIBC_NAMESPACE::acos(x); + + if (result != to_compare) { + std::cout << std::hexfloat << "Failing input: " << x << std::endl; + std::cout << std::hexfloat << "Failing output: " << result << std::endl; + std::cout << std::hexfloat << "Expected: " << to_compare << std::endl; + __builtin_trap(); + } + } mpfr_clear(input); return 0; diff --git a/libc/fuzzing/math/asin_fuzz.cpp b/libc/fuzzing/math/asin_fuzz.cpp index 94ae5c7bfdeee..e27d179606824 100644 --- a/libc/fuzzing/math/asin_fuzz.cpp +++ b/libc/fuzzing/math/asin_fuzz.cpp @@ -12,26 +12,41 @@ #include "src/math/asin.h" #include "utils/MPFRWrapper/mpfr_inc.h" +#include +#include +#include #include -extern "C" int LLVMFuzzerTestOneInput(double x) { - // remove NaN and inf and values outside accepted range - if (isnan(x) || isinf(x) || x > 1 || x < -1) - return 0; - // signed zeros already tested in unit tests - if (signbit(x) && x == 0.0) - return 0; +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { mpfr_t input; mpfr_init2(input, 53); - mpfr_set_d(input, x, MPFR_RNDN); - int output = mpfr_asin(input, input, MPFR_RNDN); - mpfr_subnormalize(input, output, MPFR_RNDN); - double to_compare = mpfr_get_d(input, MPFR_RNDN); + for (size_t i = 0; i < size / sizeof(double); ++i) { + double x; + std::memcpy(&x, data, sizeof(double)); + data += sizeof(double); - double result = LIBC_NAMESPACE::asin(x); + // remove NaN and inf and values outside accepted range + if (isnan(x) || isinf(x) || x > 1 || x < -1) + continue; - if (result != to_compare) - __builtin_trap(); + // signed zeros already tested in unit tests + if (signbit(x) && x == 0.0) + continue; + + mpfr_set_d(input, x, MPFR_RNDN); + int output = mpfr_asin(input, input, MPFR_RNDN); + mpfr_subnormalize(input, output, MPFR_RNDN); + double to_compare = mpfr_get_d(input, MPFR_RNDN); + + double result = LIBC_NAMESPACE::asin(x); + + if (result != to_compare) { + std::cout << std::hexfloat << "Failing input: " << x << std::endl; + std::cout << std::hexfloat << "Failing output: " << result << std::endl; + std::cout << std::hexfloat << "Expected: " << to_compare << std::endl; + __builtin_trap(); + } + } mpfr_clear(input); return 0; diff --git a/libc/fuzzing/math/cbrt_fuzz.cpp b/libc/fuzzing/math/cbrt_fuzz.cpp new file mode 100644 index 0000000000000..95f1df1695e56 --- /dev/null +++ b/libc/fuzzing/math/cbrt_fuzz.cpp @@ -0,0 +1,50 @@ +//===-- cbrt_fuzz.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 +// +//===----------------------------------------------------------------------===// +/// +/// Fuzzing test for llvm-libc cbrt implementation. +/// +//===----------------------------------------------------------------------===// + +#include "src/math/cbrt.h" +#include "utils/MPFRWrapper/mpfr_inc.h" +#include +#include +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + mpfr_t input; + mpfr_init2(input, 53); + for (size_t i = 0; i < size / sizeof(double); ++i) { + double x; + std::memcpy(&x, data, sizeof(double)); + data += sizeof(double); + // remove NaN and inf + if (isnan(x) || isinf(x)) + continue; + // signed zeros already tested in unit tests + if (signbit(x) && x == 0.0) + continue; + + mpfr_set_d(input, x, MPFR_RNDN); + int output = mpfr_cbrt(input, input, MPFR_RNDN); + mpfr_subnormalize(input, output, MPFR_RNDN); + double to_compare = mpfr_get_d(input, MPFR_RNDN); + + double result = LIBC_NAMESPACE::cbrt(x); + + if (result != to_compare) { + std::cout << std::hexfloat << "Failing input: " << x << std::endl; + std::cout << std::hexfloat << "Failing output: " << result << std::endl; + std::cout << std::hexfloat << "Expected: " << to_compare << std::endl; + __builtin_trap(); + } + } + mpfr_clear(input); + return 0; +} diff --git a/libc/fuzzing/math/cos_fuzz.cpp b/libc/fuzzing/math/cos_fuzz.cpp index 5b5ba0f7de717..6ed1e9ed8f309 100644 --- a/libc/fuzzing/math/cos_fuzz.cpp +++ b/libc/fuzzing/math/cos_fuzz.cpp @@ -12,28 +12,43 @@ #include "src/math/cos.h" #include "utils/MPFRWrapper/mpfr_inc.h" +#include +#include +#include #include -extern "C" int LLVMFuzzerTestOneInput(const double x) { - // remove NaN and inf as preconditions - if (isnan(x)) - return 0; - if (isinf(x)) - return 0; - // signed zeros already tested in unit tests - if (signbit(x) && x == 0.0) - return 0; +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { mpfr_t input; mpfr_init2(input, 53); - mpfr_set_d(input, x, MPFR_RNDN); - int output = mpfr_cos(input, input, MPFR_RNDN); - mpfr_subnormalize(input, output, MPFR_RNDN); - double to_compare = mpfr_get_d(input, MPFR_RNDN); + for (size_t i = 0; i < size / sizeof(double); ++i) { + double x; + std::memcpy(&x, data, sizeof(double)); + data += sizeof(double); - double result = LIBC_NAMESPACE::cos(x); + // remove NaN and inf as preconditions + if (isnan(x)) + continue; + if (isinf(x)) + continue; - if (result != to_compare) - __builtin_trap(); + // signed zeros already tested in unit tests + if (signbit(x) && x == 0.0) + continue; + + mpfr_set_d(input, x, MPFR_RNDN); + int output = mpfr_cos(input, input, MPFR_RNDN); + mpfr_subnormalize(input, output, MPFR_RNDN); + double to_compare = mpfr_get_d(input, MPFR_RNDN); + + double result = LIBC_NAMESPACE::cos(x); + + if (result != to_compare) { + std::cout << std::hexfloat << "Failing input: " << x << std::endl; + std::cout << std::hexfloat << "Failing output: " << result << std::endl; + std::cout << std::hexfloat << "Expected: " << to_compare << std::endl; + __builtin_trap(); + } + } mpfr_clear(input); return 0; diff --git a/libc/fuzzing/math/exp10_fuzz.cpp b/libc/fuzzing/math/exp10_fuzz.cpp index 2baef03a264a4..d939948b723a5 100644 --- a/libc/fuzzing/math/exp10_fuzz.cpp +++ b/libc/fuzzing/math/exp10_fuzz.cpp @@ -12,27 +12,40 @@ #include "src/math/exp10.h" #include "utils/MPFRWrapper/mpfr_inc.h" +#include +#include +#include #include -extern "C" int LLVMFuzzerTestOneInput(double x) { - // remove NaN and inf - if (isnan(x) || isinf(x)) - return 0; - // signed zeros already tested in unit tests - if (signbit(x) && x == 0.0) - return 0; +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { mpfr_t input; mpfr_init2(input, 53); - mpfr_set_d(input, x, MPFR_RNDN); - int output = mpfr_exp10(input, input, MPFR_RNDN); - mpfr_subnormalize(input, output, MPFR_RNDN); - double to_compare = mpfr_get_d(input, MPFR_RNDN); + for (size_t i = 0; i < size / sizeof(double); ++i) { + double x; + std::memcpy(&x, data, sizeof(double)); + data += sizeof(double); - double result = LIBC_NAMESPACE::exp10(x); + // remove NaN and inf + if (isnan(x) || isinf(x)) + continue; + // signed zeros already tested in unit tests + if (signbit(x) && x == 0.0) + continue; - if (result != to_compare) - __builtin_trap(); + mpfr_set_d(input, x, MPFR_RNDN); + int output = mpfr_exp10(input, input, MPFR_RNDN); + mpfr_subnormalize(input, output, MPFR_RNDN); + double to_compare = mpfr_get_d(input, MPFR_RNDN); + double result = LIBC_NAMESPACE::exp10(x); + + if (result != to_compare) { + std::cout << std::hexfloat << "Failing input: " << x << std::endl; + std::cout << std::hexfloat << "Failing output: " << result << std::endl; + std::cout << std::hexfloat << "Expected: " << to_compare << std::endl; + __builtin_trap(); + } + } mpfr_clear(input); return 0; } diff --git a/libc/fuzzing/math/exp2_fuzz.cpp b/libc/fuzzing/math/exp2_fuzz.cpp index 8a2959047a6ca..a29d3c00da672 100644 --- a/libc/fuzzing/math/exp2_fuzz.cpp +++ b/libc/fuzzing/math/exp2_fuzz.cpp @@ -12,27 +12,40 @@ #include "src/math/exp2.h" #include "utils/MPFRWrapper/mpfr_inc.h" +#include +#include +#include #include -extern "C" int LLVMFuzzerTestOneInput(double x) { - // remove NaN and inf - if (isnan(x) || isinf(x)) - return 0; - // signed zeros already tested in unit tests - if (signbit(x) && x == 0.0) - return 0; +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { mpfr_t input; mpfr_init2(input, 53); - mpfr_set_d(input, x, MPFR_RNDN); - int output = mpfr_exp2(input, input, MPFR_RNDN); - mpfr_subnormalize(input, output, MPFR_RNDN); - double to_compare = mpfr_get_d(input, MPFR_RNDN); + for (size_t i = 0; i < size / sizeof(double); ++i) { + double x; + std::memcpy(&x, data, sizeof(double)); + data += sizeof(double); - double result = LIBC_NAMESPACE::exp2(x); + // remove NaN and inf + if (isnan(x) || isinf(x)) + continue; + // signed zeros already tested in unit tests + if (signbit(x) && x == 0.0) + continue; - if (result != to_compare) - __builtin_trap(); + mpfr_set_d(input, x, MPFR_RNDN); + int output = mpfr_exp2(input, input, MPFR_RNDN); + mpfr_subnormalize(input, output, MPFR_RNDN); + double to_compare = mpfr_get_d(input, MPFR_RNDN); + double result = LIBC_NAMESPACE::exp2(x); + + if (result != to_compare) { + std::cout << std::hexfloat << "Failing input: " << x << std::endl; + std::cout << std::hexfloat << "Failing output: " << result << std::endl; + std::cout << std::hexfloat << "Expected: " << to_compare << std::endl; + __builtin_trap(); + } + } mpfr_clear(input); return 0; } diff --git a/libc/fuzzing/math/exp_fuzz.cpp b/libc/fuzzing/math/exp_fuzz.cpp index 97bc12dfa64c9..66823596dc6fa 100644 --- a/libc/fuzzing/math/exp_fuzz.cpp +++ b/libc/fuzzing/math/exp_fuzz.cpp @@ -12,27 +12,40 @@ #include "src/math/exp.h" #include "utils/MPFRWrapper/mpfr_inc.h" +#include +#include +#include #include -extern "C" int LLVMFuzzerTestOneInput(double x) { - // remove NaN and inf - if (isnan(x) || isinf(x)) - return 0; - // signed zeros already tested in unit tests - if (signbit(x) && x == 0.0) - return 0; +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { mpfr_t input; mpfr_init2(input, 53); - mpfr_set_d(input, x, MPFR_RNDN); - int output = mpfr_exp(input, input, MPFR_RNDN); - mpfr_subnormalize(input, output, MPFR_RNDN); - double to_compare = mpfr_get_d(input, MPFR_RNDN); + for (size_t i = 0; i < size / sizeof(double); ++i) { + double x; + std::memcpy(&x, data, sizeof(double)); + data += sizeof(double); - double result = LIBC_NAMESPACE::exp(x); + // remove NaN and inf + if (isnan(x) || isinf(x)) + continue; + // signed zeros already tested in unit tests + if (signbit(x) && x == 0.0) + continue; - if (result != to_compare) - __builtin_trap(); + mpfr_set_d(input, x, MPFR_RNDN); + int output = mpfr_exp(input, input, MPFR_RNDN); + mpfr_subnormalize(input, output, MPFR_RNDN); + double to_compare = mpfr_get_d(input, MPFR_RNDN); + double result = LIBC_NAMESPACE::exp(x); + + if (result != to_compare) { + std::cout << std::hexfloat << "Failing input: " << x << std::endl; + std::cout << std::hexfloat << "Failing output: " << result << std::endl; + std::cout << std::hexfloat << "Expected: " << to_compare << std::endl; + __builtin_trap(); + } + } mpfr_clear(input); return 0; } diff --git a/libc/fuzzing/math/expm1_fuzz.cpp b/libc/fuzzing/math/expm1_fuzz.cpp index db507bb02b1d7..0690e449c3d23 100644 --- a/libc/fuzzing/math/expm1_fuzz.cpp +++ b/libc/fuzzing/math/expm1_fuzz.cpp @@ -12,27 +12,40 @@ #include "src/math/expm1.h" #include "utils/MPFRWrapper/mpfr_inc.h" +#include +#include +#include #include -extern "C" int LLVMFuzzerTestOneInput(double x) { - // remove NaN and inf - if (isnan(x) || isinf(x)) - return 0; - // signed zeros already tested in unit tests - if (signbit(x) && x == 0.0) - return 0; +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { mpfr_t input; mpfr_init2(input, 53); - mpfr_set_d(input, x, MPFR_RNDN); - int output = mpfr_expm1(input, input, MPFR_RNDN); - mpfr_subnormalize(input, output, MPFR_RNDN); - double to_compare = mpfr_get_d(input, MPFR_RNDN); + for (size_t i = 0; i < size / sizeof(double); ++i) { + double x; + std::memcpy(&x, data, sizeof(double)); + data += sizeof(double); - double result = LIBC_NAMESPACE::expm1(x); + // remove NaN and inf + if (isnan(x) || isinf(x)) + continue; + // signed zeros already tested in unit tests + if (signbit(x) && x == 0.0) + continue; - if (result != to_compare) - __builtin_trap(); + mpfr_set_d(input, x, MPFR_RNDN); + int output = mpfr_expm1(input, input, MPFR_RNDN); + mpfr_subnormalize(input, output, MPFR_RNDN); + double to_compare = mpfr_get_d(input, MPFR_RNDN); + double result = LIBC_NAMESPACE::expm1(x); + + if (result != to_compare) { + std::cout << std::hexfloat << "Failing input: " << x << std::endl; + std::cout << std::hexfloat << "Failing output: " << result << std::endl; + std::cout << std::hexfloat << "Expected: " << to_compare << std::endl; + __builtin_trap(); + } + } mpfr_clear(input); return 0; } diff --git a/libc/fuzzing/math/log10_fuzz.cpp b/libc/fuzzing/math/log10_fuzz.cpp index 23134f4903a45..369408cc288b5 100644 --- a/libc/fuzzing/math/log10_fuzz.cpp +++ b/libc/fuzzing/math/log10_fuzz.cpp @@ -27,10 +27,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // remove NaN and inf and values outside accepted range if (isnan(x) || isinf(x) || x < 0) - return 0; + continue; // signed zeros already tested in unit tests if (signbit(x) && x == 0.0) - return 0; + continue; mpfr_set_d(input, x, MPFR_RNDN); int output = mpfr_log10(input, input, MPFR_RNDN); diff --git a/libc/fuzzing/math/log1p_fuzz.cpp b/libc/fuzzing/math/log1p_fuzz.cpp index 5e138a65e3716..e02c61a352c1f 100644 --- a/libc/fuzzing/math/log1p_fuzz.cpp +++ b/libc/fuzzing/math/log1p_fuzz.cpp @@ -26,10 +26,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { data += sizeof(double); // remove NaN and inf and values outside accepted range if (isnan(x) || isinf(x) || x < -1) - return 0; + continue; // signed zeros already tested in unit tests if (signbit(x) && x == 0.0) - return 0; + continue; mpfr_set_d(input, x, MPFR_RNDN); int output = mpfr_log1p(input, input, MPFR_RNDN); diff --git a/libc/fuzzing/math/log2_fuzz.cpp b/libc/fuzzing/math/log2_fuzz.cpp index aa19649b95126..c3e53c639cba9 100644 --- a/libc/fuzzing/math/log2_fuzz.cpp +++ b/libc/fuzzing/math/log2_fuzz.cpp @@ -27,10 +27,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // remove NaN and inf and values outside accepted range if (isnan(x) || isinf(x) || x < 0) - return 0; + continue; // signed zeros already tested in unit tests if (signbit(x) && x == 0.0) - return 0; + continue; mpfr_set_d(input, x, MPFR_RNDN); int output = mpfr_log2(input, input, MPFR_RNDN); diff --git a/libc/fuzzing/math/log_fuzz.cpp b/libc/fuzzing/math/log_fuzz.cpp index 03aa678d1f16c..9618accf3db26 100644 --- a/libc/fuzzing/math/log_fuzz.cpp +++ b/libc/fuzzing/math/log_fuzz.cpp @@ -27,10 +27,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // remove NaN and inf and values outside accepted range if (isnan(x) || isinf(x) || x < 0) - return 0; + continue; // signed zeros already tested in unit tests if (signbit(x) && x == 0.0) - return 0; + continue; mpfr_set_d(input, x, MPFR_RNDN); int output = mpfr_log(input, input, MPFR_RNDN); mpfr_subnormalize(input, output, MPFR_RNDN); diff --git a/libc/fuzzing/math/sin_fuzz.cpp b/libc/fuzzing/math/sin_fuzz.cpp index a5f0fa95c1581..f6d59c7e496bc 100644 --- a/libc/fuzzing/math/sin_fuzz.cpp +++ b/libc/fuzzing/math/sin_fuzz.cpp @@ -12,28 +12,43 @@ #include "src/math/sin.h" #include "utils/MPFRWrapper/mpfr_inc.h" +#include +#include +#include #include -extern "C" int LLVMFuzzerTestOneInput(const double x) { - // remove NaN and inf as preconditions - if (isnan(x)) - return 0; - if (isinf(x)) - return 0; - // signed zeros already tested in unit tests - if (signbit(x) && x == 0.0) - return 0; +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { mpfr_t input; mpfr_init2(input, 53); - mpfr_set_d(input, x, MPFR_RNDN); - int output = mpfr_sin(input, input, MPFR_RNDN); - mpfr_subnormalize(input, output, MPFR_RNDN); - double to_compare = mpfr_get_d(input, MPFR_RNDN); + for (size_t i = 0; i < size / sizeof(double); ++i) { + double x; + std::memcpy(&x, data, sizeof(double)); + data += sizeof(double); - double result = LIBC_NAMESPACE::sin(x); + // remove NaN and inf as preconditions + if (isnan(x)) + continue; + if (isinf(x)) + continue; - if (result != to_compare) - __builtin_trap(); + // signed zeros already tested in unit tests + if (signbit(x) && x == 0.0) + continue; + + mpfr_set_d(input, x, MPFR_RNDN); + int output = mpfr_sin(input, input, MPFR_RNDN); + mpfr_subnormalize(input, output, MPFR_RNDN); + double to_compare = mpfr_get_d(input, MPFR_RNDN); + + double result = LIBC_NAMESPACE::sin(x); + + if (result != to_compare) { + std::cout << std::hexfloat << "Failing input: " << x << std::endl; + std::cout << std::hexfloat << "Failing output: " << result << std::endl; + std::cout << std::hexfloat << "Expected: " << to_compare << std::endl; + __builtin_trap(); + } + } mpfr_clear(input); return 0; diff --git a/libc/fuzzing/math/sincos_fuzz.cpp b/libc/fuzzing/math/sincos_fuzz.cpp index fd3dfae23168c..3d3306721fc47 100644 --- a/libc/fuzzing/math/sincos_fuzz.cpp +++ b/libc/fuzzing/math/sincos_fuzz.cpp @@ -12,15 +12,12 @@ #include "src/math/sincos.h" #include "utils/MPFRWrapper/mpfr_inc.h" +#include +#include +#include #include -extern "C" int LLVMFuzzerTestOneInput(double x) { - // remove NaN and inf as preconditions - if (isnan(x) || isinf(x)) - return 0; - // signed zeros already tested in unit tests - if (signbit(x) && x == 0.0) - return 0; +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { mpfr_t input; mpfr_t sin_x; mpfr_t cos_x; @@ -28,21 +25,43 @@ extern "C" int LLVMFuzzerTestOneInput(double x) { mpfr_init2(input, 53); mpfr_init2(sin_x, 53); mpfr_init2(cos_x, 53); + for (size_t i = 0; i < size / sizeof(double); ++i) { + double x; + std::memcpy(&x, data, sizeof(double)); + data += sizeof(double); - mpfr_set_d(input, x, MPFR_RNDN); + // remove NaN and inf as preconditions + if (isnan(x) || isinf(x)) + continue; - int output = mpfr_sin_cos(sin_x, cos_x, input, MPFR_RNDN); - mpfr_subnormalize(sin_x, output, MPFR_RNDN); - mpfr_subnormalize(cos_x, output, MPFR_RNDN); + // signed zeros already tested in unit tests + if (signbit(x) && x == 0.0) + continue; - double to_compare_sin = mpfr_get_d(sin_x, MPFR_RNDN); - double to_compare_cos = mpfr_get_d(cos_x, MPFR_RNDN); + mpfr_set_d(input, x, MPFR_RNDN); + int output = mpfr_sin_cos(sin_x, cos_x, input, MPFR_RNDN); + mpfr_subnormalize(sin_x, output, MPFR_RNDN); + mpfr_subnormalize(cos_x, output, MPFR_RNDN); - double sin_res, cos_res; - LIBC_NAMESPACE::sincos(x, &sin_res, &cos_res); + double to_compare_sin = mpfr_get_d(sin_x, MPFR_RNDN); + double to_compare_cos = mpfr_get_d(cos_x, MPFR_RNDN); - if (sin_res != to_compare_sin || cos_res != to_compare_cos) - __builtin_trap(); + double sin_res, cos_res; + LIBC_NAMESPACE::sincos(x, &sin_res, &cos_res); + + if (sin_res != to_compare_sin || cos_res != to_compare_cos) { + std::cout << std::hexfloat << "Failing input: " << x << std::endl; + std::cout << std::hexfloat << "Failing sin output: " << sin_res + << std::endl; + std::cout << std::hexfloat << "Expected sin: " << to_compare_sin + << std::endl; + std::cout << std::hexfloat << "Failing cos output: " << cos_res + << std::endl; + std::cout << std::hexfloat << "Expected cos: " << to_compare_cos + << std::endl; + __builtin_trap(); + } + } mpfr_clear(input); mpfr_clear(sin_x); diff --git a/libc/fuzzing/math/sqrt_fuzz.cpp b/libc/fuzzing/math/sqrt_fuzz.cpp index e81cf1afd3728..969b4f58e342c 100644 --- a/libc/fuzzing/math/sqrt_fuzz.cpp +++ b/libc/fuzzing/math/sqrt_fuzz.cpp @@ -26,10 +26,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { data += sizeof(double); // remove NaN and inf and values outside accepted range if (isnan(x) || isinf(x) || x < 0) - return 0; + continue; // signed zeros already tested in unit tests if (signbit(x) && x == 0.0) - return 0; + continue; mpfr_set_d(input, x, MPFR_RNDN); int output = mpfr_sqrt(input, input, MPFR_RNDN); diff --git a/libc/fuzzing/math/tan_fuzz.cpp b/libc/fuzzing/math/tan_fuzz.cpp index 2a462fa34fce4..63d3b12866a0e 100644 --- a/libc/fuzzing/math/tan_fuzz.cpp +++ b/libc/fuzzing/math/tan_fuzz.cpp @@ -12,28 +12,43 @@ #include "src/math/tan.h" #include "utils/MPFRWrapper/mpfr_inc.h" +#include +#include +#include #include -extern "C" int LLVMFuzzerTestOneInput(const double x) { - // remove NaN and inf as preconditions - if (isnan(x)) - return 0; - if (isinf(x)) - return 0; - // signed zeros already tested in unit tests - if (signbit(x) && x == 0.0) - return 0; +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { mpfr_t input; mpfr_init2(input, 53); - mpfr_set_d(input, x, MPFR_RNDN); - int output = mpfr_tan(input, input, MPFR_RNDN); - mpfr_subnormalize(input, output, MPFR_RNDN); - double to_compare = mpfr_get_d(input, MPFR_RNDN); + for (size_t i = 0; i < size / sizeof(double); ++i) { + double x; + std::memcpy(&x, data, sizeof(double)); + data += sizeof(double); - double result = LIBC_NAMESPACE::tan(x); + // remove NaN and inf as preconditions + if (isnan(x)) + continue; + if (isinf(x)) + continue; - if (result != to_compare) - __builtin_trap(); + // signed zeros already tested in unit tests + if (signbit(x) && x == 0.0) + continue; + + mpfr_set_d(input, x, MPFR_RNDN); + int output = mpfr_tan(input, input, MPFR_RNDN); + mpfr_subnormalize(input, output, MPFR_RNDN); + double to_compare = mpfr_get_d(input, MPFR_RNDN); + + double result = LIBC_NAMESPACE::tan(x); + + if (result != to_compare) { + std::cout << std::hexfloat << "Failing input: " << x << std::endl; + std::cout << std::hexfloat << "Failing output: " << result << std::endl; + std::cout << std::hexfloat << "Expected: " << to_compare << std::endl; + __builtin_trap(); + } + } mpfr_clear(input); return 0; diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt index e4b3cb0faa820..f3bdc9f6aedd1 100644 --- a/libc/hdr/types/CMakeLists.txt +++ b/libc/hdr/types/CMakeLists.txt @@ -26,6 +26,8 @@ add_proxy_header_library( mbstate_t.h DEPENDS libc.include.llvm-libc-types.mbstate_t + FULL_BUILD_DEPENDS + libc.include.uchar ) add_proxy_header_library( diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt index 55268d19529c7..73213826ad607 100644 --- a/libc/include/CMakeLists.txt +++ b/libc/include/CMakeLists.txt @@ -69,7 +69,6 @@ add_header_macro( ../libc/include/dlfcn.yaml dlfcn.h DEPENDS - .llvm-libc-macros.dlfcn_macros .llvm_libc_common_h ) @@ -720,6 +719,15 @@ add_header_macro( .llvm-libc-types.wchar_t ) +add_header_macro( + wctype + ../libc/include/wctype.yaml + wctype.h + DEPENDS + .llvm_libc_common_h + .llvm-libc-types.wint_t +) + add_header_macro( locale ../libc/include/locale.yaml diff --git a/libc/include/dirent.yaml b/libc/include/dirent.yaml index 3fc522fda80e4..66570bca6c495 100644 --- a/libc/include/dirent.yaml +++ b/libc/include/dirent.yaml @@ -1,47 +1,45 @@ header: dirent.h -header_template: dirent.h.def -macros: [] +standards: + - posix types: - type_name: struct_dirent - type_name: DIR - type_name: ino_t -enums: [] -objects: [] functions: - name: alphasort standards: - - POSIX + - posix return_type: int arguments: - type: const struct dirent ** - type: const struct dirent ** - name: closedir standards: - - POSIX + - posix return_type: int arguments: - type: DIR * - name: dirfd standards: - - POSIX + - posix return_type: int arguments: - type: DIR * - name: fdopendir standards: - - POSIX + - posix return_type: DIR * arguments: - type: int - name: opendir standards: - - POSIX + - posix return_type: DIR * arguments: - type: const char * - name: readdir standards: - - POSIX + - posix return_type: struct dirent * arguments: - type: DIR * diff --git a/libc/include/dlfcn.yaml b/libc/include/dlfcn.yaml index 78bbeff4e60d9..28be34dbd95bd 100644 --- a/libc/include/dlfcn.yaml +++ b/libc/include/dlfcn.yaml @@ -1,17 +1,34 @@ header: dlfcn.h -header_template: dlfcn.h.def +standards: + - posix macros: + # Note that macro values are quoted to keep the integer literals as + # written. Without the quotes, YAML will normalize them to minimal + # decimal, which is less readable for humans seeing the generated header. - macro_name: RTLD_LAZY - macro_header: dlfcn-macros.h + macro_value: "0x00001" - macro_name: RTLD_NOW - macro_header: dlfcn-macros.h + macro_value: "0x00002" - macro_name: RTLD_GLOBAL - macro_header: dlfcn-macros.h + macro_value: "0x00100" - macro_name: RTLD_LOCAL - macro_header: dlfcn-macros.h -types: [] -enums: [] -objects: [] + macro_value: "0" + - macro_name: RTLD_BINDING_MASK + standards: + - gnu + macro_value: "0x00003" + - macro_name: RTLD_NOLOAD + standards: + - gnu + macro_value: "0x00004" + - macro_name: RTLD_DEEPBIND + standards: + - gnu + macro_value: "0x00008" + - macro_name: RTLD_NODELETE + standards: + - gnu + macro_value: "0x01000" functions: - name: dlclose standards: diff --git a/libc/include/llvm-libc-macros/dlfcn-macros.h b/libc/include/llvm-libc-macros/dlfcn-macros.h deleted file mode 100644 index dcd202b9ab435..0000000000000 --- a/libc/include/llvm-libc-macros/dlfcn-macros.h +++ /dev/null @@ -1,23 +0,0 @@ -//===-- Definition of macros from dlfcn.h ---------------------------------===// -// -// 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_LIBC_MACROS_DLFCN_MACROS_H -#define LLVM_LIBC_MACROS_DLFCN_MACROS_H - -#define RTLD_LAZY 0x00001 -#define RTLD_NOW 0x00002 -#define RTLD_GLOBAL 0x00100 -#define RTLD_LOCAL 0 - -// Non-standard stuff here -#define RTLD_BINDING_MASK 0x3 -#define RTLD_NOLOAD 0x00004 -#define RTLD_DEEPBIND 0x00008 -#define RTLD_NODELETE 0x01000 - -#endif // LLVM_LIBC_MACROS_DLFCN_MACROS_H diff --git a/libc/include/llvm-libc-macros/math-macros.h b/libc/include/llvm-libc-macros/math-macros.h index 2f05d7544666e..6697ce5b03851 100644 --- a/libc/include/llvm-libc-macros/math-macros.h +++ b/libc/include/llvm-libc-macros/math-macros.h @@ -50,4 +50,105 @@ #define math_errhandling (MATH_ERRNO | MATH_ERREXCEPT) #endif +// POSIX math constants +// https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/math.h.html +#define M_E (__extension__ 0x1.5bf0a8b145769p1) +#define M_EGAMMA (__extension__ 0x1.2788cfc6fb619p-1) +#define M_LOG2E (__extension__ 0x1.71547652b82fep0) +#define M_LOG10E (__extension__ 0x1.bcb7b1526e50ep-2) +#define M_LN2 (__extension__ 0x1.62e42fefa39efp-1) +#define M_LN10 (__extension__ 0x1.26bb1bbb55516p1) +#define M_PHI (__extension__ 0x1.9e3779b97f4a8p0) +#define M_PI (__extension__ 0x1.921fb54442d18p1) +#define M_PI_2 (__extension__ 0x1.921fb54442d18p0) +#define M_PI_4 (__extension__ 0x1.921fb54442d18p-1) +#define M_1_PI (__extension__ 0x1.45f306dc9c883p-2) +#define M_1_SQRTPI (__extension__ 0x1.20dd750429b6dp-1) +#define M_2_PI (__extension__ 0x1.45f306dc9c883p-1) +#define M_2_SQRTPI (__extension__ 0x1.20dd750429b6dp0) +#define M_SQRT2 (__extension__ 0x1.6a09e667f3bcdp0) +#define M_SQRT3 (__extension__ 0x1.bb67ae8584caap0) +#define M_SQRT1_2 (__extension__ 0x1.6a09e667f3bcdp-1) +#define M_SQRT1_3 (__extension__ 0x1.279a74590331cp-1) + +#define M_Ef (__extension__ 0x1.5bf0a8p1f) +#define M_EGAMMAf (__extension__ 0x1.2788dp-1f) +#define M_LOG2Ef (__extension__ 0x1.715476p0f) +#define M_LOG10Ef (__extension__ 0x1.bcb7b2p-2f) +#define M_LN2f (__extension__ 0x1.62e43p-1f) +#define M_LN10f (__extension__ 0x1.26bb1cp1f) +#define M_PHIf (__extension__ 0x1.9e377ap0f) +#define M_PIf (__extension__ 0x1.921fb6p1f) +#define M_PI_2f (__extension__ 0x1.921fb6p0f) +#define M_PI_4f (__extension__ 0x1.921fb6p-1f) +#define M_1_PIf (__extension__ 0x1.45f306p-2f) +#define M_1_SQRTPIf (__extension__ 0x1.20dd76p-1f) +#define M_2_PIf (__extension__ 0x1.45f306p-1f) +#define M_2_SQRTPIf (__extension__ 0x1.20dd76p0f) +#define M_SQRT2f (__extension__ 0x1.6a09e6p0f) +#define M_SQRT3f (__extension__ 0x1.bb67aep0f) +#define M_SQRT1_2f (__extension__ 0x1.6a09e6p-1f) +#define M_SQRT1_3f (__extension__ 0x1.279a74p-1f) + +#define M_El (__extension__ 0x1.5bf0a8b1457695355fb8ac404e7ap1L) +#define M_EGAMMAl (__extension__ 0x1.2788cfc6fb618f49a37c7f0202a6p-1L) +#define M_LOG2El (__extension__ 0x1.71547652b82fe1777d0ffda0d23ap0L) +#define M_LOG10El (__extension__ 0x1.bcb7b1526e50e32a6ab7555f5a68p-2L) +#define M_LN2l (__extension__ 0x1.62e42fefa39ef35793c7673007e6p-1L) +#define M_LN10l (__extension__ 0x1.26bb1bbb5551582dd4adac5705a6p1L) +#define M_PHIl (__extension__ 0x1.9e3779b97f4a7c15f39cc0605ceep0L) +#define M_PIl (__extension__ 0x1.921fb54442d18469898cc51701b8p1L) +#define M_PI_2l (__extension__ 0x1.921fb54442d18469898cc51701b8p0L) +#define M_PI_4l (__extension__ 0x1.921fb54442d18469898cc51701b8p-1L) +#define M_1_PIl (__extension__ 0x1.45f306dc9c882a53f84eafa3ea6ap-2L) +#define M_1_SQRTPIl (__extension__ 0x1.20dd750429b6d11ae3a914fed7fep-1L) +#define M_2_PIl (__extension__ 0x1.45f306dc9c882a53f84eafa3ea6ap-1L) +#define M_2_SQRTPIl (__extension__ 0x1.20dd750429b6d11ae3a914fed7fep0L) +#define M_SQRT2l (__extension__ 0x1.6a09e667f3bcc908b2fb1366ea95p0L) +#define M_SQRT3l (__extension__ 0x1.bb67ae8584caa73b25742d7078b8p0L) +#define M_SQRT1_2l (__extension__ 0x1.6a09e667f3bcc908b2fb1366ea95p-1L) +#define M_SQRT1_3l (__extension__ 0x1.279a74590331c4d218f81e4afb25p-1L) + +#ifdef __FLT16_MANT_DIG__ +#define M_Ef16 (__extension__ 0x1.5cp1f16) +#define M_EGAMMAf16 (__extension__ 0x1.278p-1f16) +#define M_LOG2Ef16 (__extension__ 0x1.714f16) +#define M_LOG10Ef16 (__extension__ 0x1.bccp-2f16) +#define M_LN2f16 (__extension__ 0x1.63p-1f16) +#define M_LN10f16 (__extension__ 0x1.26cp1f16) +#define M_PHIf16 (__extension__ 0x1.9e4p0f16) +#define M_PIf16 (__extension__ 0x1.92p1f16) +#define M_PI_2f16 (__extension__ 0x1.92p0f16) +#define M_PI_4f16 (__extension__ 0x1.92p-1f16) +#define M_1_PIf16 (__extension__ 0x1.46p-2f16) +#define M_1_SQRTPIf16 (__extension__ 0x1.20cp-1f16) +#define M_2_PIf16 (__extension__ 0x1.46p-1f16) +#define M_2_SQRTPIf16 (__extension__ 0x1.20cp0f16) +#define M_SQRT2f16 (__extension__ 0x1.6ap0f16) +#define M_SQRT3f16 (__extension__ 0x1.bb8p0f16) +#define M_SQRT1_2f16 (__extension__ 0x1.6ap-1f16) +#define M_SQRT1_3f16 (__extension__ 0x1.278p-1f16) +#endif // __FLT16_MANT_DIG__ + +#ifdef __SIZEOF_FLOAT128__ +#define M_Ef128 (__extension__ 0x1.5bf0a8b1457695355fb8ac404e7ap1q) +#define M_EGAMMAf128 (__extension__ 0x1.2788cfc6fb618f49a37c7f0202a6p-1q) +#define M_LOG2Ef128 (__extension__ 0x1.71547652b82fe1777d0ffda0d23ap0q) +#define M_LOG10Ef128 (__extension__ 0x1.bcb7b1526e50e32a6ab7555f5a68p-2q) +#define M_LN2f128 (__extension__ 0x1.62e42fefa39ef35793c7673007e6p-1q) +#define M_LN10f128 (__extension__ 0x1.26bb1bbb5551582dd4adac5705a6p1q) +#define M_PHIf128 (__extension__ 0x1.9e3779b97f4a7c15f39cc0605ceep0q) +#define M_PIf128 (__extension__ 0x1.921fb54442d18469898cc51701b8p1q) +#define M_PI_2f128 (__extension__ 0x1.921fb54442d18469898cc51701b8p0q) +#define M_PI_4f128 (__extension__ 0x1.921fb54442d18469898cc51701b8p-1q) +#define M_1_PIf128 (__extension__ 0x1.45f306dc9c882a53f84eafa3ea6ap-2q) +#define M_1_SQRTPIf128 (__extension__ 0x1.20dd750429b6d11ae3a914fed7fep-1q) +#define M_2_PIf128 (__extension__ 0x1.45f306dc9c882a53f84eafa3ea6ap-1q) +#define M_2_SQRTPIf128 (__extension__ 0x1.20dd750429b6d11ae3a914fed7fep0q) +#define M_SQRT2f128 (__extension__ 0x1.6a09e667f3bcc908b2fb1366ea95p0q) +#define M_SQRT3f128 (__extension__ 0x1.bb67ae8584caa73b25742d7078b8p0q) +#define M_SQRT1_2f128 (__extension__ 0x1.6a09e667f3bcc908b2fb1366ea95p-1q) +#define M_SQRT1_3f128 (__extension__ 0x1.279a74590331c4d218f81e4afb25p-1q) +#endif // __SIZEOF_FLOAT128__ + #endif // LLVM_LIBC_MACROS_MATH_MACROS_H diff --git a/libc/include/math.yaml b/libc/include/math.yaml index 3044ec3437ff8..007be235f4380 100644 --- a/libc/include/math.yaml +++ b/libc/include/math.yaml @@ -33,14 +33,14 @@ functions: return_type: float arguments: - type: float - name: acoshf16 + - name: acoshf16 standards: - stdc return_type: _Float16 arguments: - type: _Float16 guard: LIBC_TYPES_HAS_FLOAT16 - name: acospif16 + - name: acospif16 standards: - stdc return_type: _Float16 diff --git a/libc/include/search.yaml b/libc/include/search.yaml index e0247afad2cd6..8a3a0c50af60f 100644 --- a/libc/include/search.yaml +++ b/libc/include/search.yaml @@ -1,6 +1,6 @@ header: search.h -header_template: search.h.def -macros: [] +standards: + - posix types: - type_name: ACTION - type_name: ENTRY @@ -12,35 +12,35 @@ objects: [] functions: - name: hcreate standards: - - POSIX + - posix return_type: int arguments: - type: size_t - name: hcreate_r - standards: GNUExtensions + standards: gnu return_type: int arguments: - type: size_t - type: struct hsearch_data * - name: hdestroy - standards: GNUExtensions + standards: gnu return_type: void arguments: [] - name: hdestroy_r standards: - - POSIX + - posix return_type: void arguments: - type: struct hsearch_data * - name: hsearch standards: - - POSIX + - posix return_type: ENTRY * arguments: - type: ENTRY - type: ACTION - name: hsearch_r - standards: GNUExtensions + standards: gnu return_type: int arguments: - type: ENTRY @@ -49,20 +49,20 @@ functions: - type: struct hsearch_data * - name: insque standards: - - POSIX + - posix return_type: void arguments: - type: void * - type: void * - name: remque standards: - - POSIX + - posix return_type: void arguments: - type: void * - name: lfind standards: - - POSIX + - posix return_type: void * arguments: - type: const void * @@ -72,7 +72,7 @@ functions: - type: __search_compare_t - name: lsearch standards: - - POSIX + - posix return_type: void * arguments: - type: const void * diff --git a/libc/include/setjmp.yaml b/libc/include/setjmp.yaml index 00049e58c86c8..55e03470e33ca 100644 --- a/libc/include/setjmp.yaml +++ b/libc/include/setjmp.yaml @@ -1,10 +1,8 @@ header: setjmp.h -header_template: setjmp.h.def -macros: [] +standards: + - stdc types: - type_name: jmp_buf -enums: [] -objects: [] functions: - name: longjmp standards: @@ -23,7 +21,7 @@ functions: - type: jmp_buf - name: sigsetjmp standards: - - POSIX + - posix return_type: int attributes: - _Returns_twice @@ -32,7 +30,7 @@ functions: - type: int - name: siglongjmp standards: - - POSIX + - posix return_type: _Noreturn void arguments: - type: sigjmp_buf diff --git a/libc/include/spawn.yaml b/libc/include/spawn.yaml index c763cc76fd094..ef39f66d080f6 100644 --- a/libc/include/spawn.yaml +++ b/libc/include/spawn.yaml @@ -1,17 +1,15 @@ header: spawn.h -header_template: spawn.h.def -macros: [] +standards: + - posix types: - type_name: posix_spawn_file_actions_t - type_name: posix_spawnattr_t - type_name: pid_t - type_name: mode_t -enums: [] -objects: [] functions: - name: posix_spawn standards: - - POSIX + - posix return_type: int arguments: - type: pid_t *__restrict @@ -22,14 +20,14 @@ functions: - type: char * const * __restrict - name: posix_spawn_file_actions_addclose standards: - - POSIX + - posix return_type: int arguments: - type: posix_spawn_file_actions_t * - type: int - name: posix_spawn_file_actions_adddup2 standards: - - POSIX + - posix return_type: int arguments: - type: posix_spawn_file_actions_t * @@ -37,7 +35,7 @@ functions: - type: int - name: posix_spawn_file_actions_addopen standards: - - POSIX + - posix return_type: int arguments: - type: posix_spawn_file_actions_t *__restrict @@ -47,13 +45,13 @@ functions: - type: mode_t - name: posix_spawn_file_actions_destroy standards: - - POSIX + - posix return_type: int arguments: - type: posix_spawn_file_actions_t * - name: posix_spawn_file_actions_init standards: - - POSIX + - posix return_type: int arguments: - type: posix_spawn_file_actions_t * diff --git a/libc/include/string.yaml b/libc/include/string.yaml index 736deceb453de..0bf297ee747a4 100644 --- a/libc/include/string.yaml +++ b/libc/include/string.yaml @@ -1,5 +1,6 @@ header: string.h -header_template: string.h.def +standards: + - stdc macros: - macro_name: NULL macro_header: null-macro.h @@ -11,7 +12,7 @@ objects: [] functions: - name: memccpy standards: - - POSIX + - posix return_type: void * arguments: - type: void *__restrict @@ -61,7 +62,7 @@ functions: - type: size_t - name: mempcpy standards: - - POSIX + - posix return_type: void * arguments: - type: void *__restrict @@ -93,14 +94,14 @@ functions: - type: size_t - name: stpcpy standards: - - POSIX + - posix return_type: char * arguments: - type: char *__restrict - type: const char *__restrict - name: stpncpy standards: - - POSIX + - posix return_type: char * arguments: - type: char *__restrict @@ -243,7 +244,7 @@ functions: - type: size_t - name: strnlen standards: - - POSIX + - posix return_type: size_t arguments: - type: const char * @@ -271,7 +272,7 @@ functions: - type: const char *__restrict - name: strsignal standards: - - POSIX + - posix return_type: char * arguments: - type: int @@ -298,7 +299,7 @@ functions: - type: const char *__restrict - name: strtok_r standards: - - POSIX + - posix return_type: char * arguments: - type: char *__restrict diff --git a/libc/include/strings.h.def b/libc/include/strings.h.def deleted file mode 100644 index 9b016bf0bc50b..0000000000000 --- a/libc/include/strings.h.def +++ /dev/null @@ -1,16 +0,0 @@ -//===-- C standard library header strings.h -------------------------------===// -// -// 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_LIBC_STRINGS_H -#define LLVM_LIBC_STRINGS_H - -#include "__llvm-libc-common.h" - -%%public_api() - -#endif // LLVM_LIBC_STRINGS_H diff --git a/libc/include/strings.yaml b/libc/include/strings.yaml index 855800d9dbc3d..1e78f0e48aa59 100644 --- a/libc/include/strings.yaml +++ b/libc/include/strings.yaml @@ -1,15 +1,14 @@ header: strings.h -header_template: strings.h.def -macros: [] +standards: + - bsd + - posix types: - type_name: size_t - type_name: locale_t -enums: [] -objects: [] functions: - name: bcmp standards: - - llvm_libc_ext + - bsd return_type: int arguments: - type: const void * @@ -17,7 +16,7 @@ functions: - type: size_t - name: bcopy standards: - - llvm_libc_ext + - bsd return_type: void arguments: - type: const void * @@ -25,69 +24,61 @@ functions: - type: size_t - name: bzero standards: - - llvm_libc_ext + - bsd return_type: void arguments: - type: void * - type: size_t - name: ffs standards: - - POSIX + - posix return_type: int arguments: - type: int - name: ffsl standards: - - POSIX + - posix return_type: int arguments: - type: long - name: ffsll standards: - - POSIX + - posix return_type: int arguments: - type: long long - name: index standards: - - BSDExtensions + - bsd return_type: char * arguments: - type: const char * - type: int - name: rindex standards: - - BSDExtensions + - bsd return_type: char * arguments: - type: const char * - type: int - name: strcasecmp - standards: - - BSDExtensions return_type: int arguments: - type: const char * - type: const char * - name: strcasecmp_l - standards: - - BSDExtensions return_type: int arguments: - type: const char * - type: const char * - type: locale_t - name: strncasecmp - standards: - - BSDExtensions return_type: int arguments: - type: const char * - type: const char * - type: size_t - name: strncasecmp_l - standards: - - BSDExtensions return_type: int arguments: - type: const char * diff --git a/libc/include/sys/sendfile.h.def b/libc/include/sys/sendfile.h.def deleted file mode 100644 index d7f21f91f95ed..0000000000000 --- a/libc/include/sys/sendfile.h.def +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Linux sys/sendfile.h ----------------------------------------------===// -// -// 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_LIBC_SYS_SENDFILE_H -#define LLVM_LIBC_SYS_SENDFILE_H - -#include "__llvm-libc-common.h" - -%%public_api() - -#endif // LLVM_LIBC_SYS_SENDFILE_H diff --git a/libc/include/sys/sendfile.yaml b/libc/include/sys/sendfile.yaml index 259ab83dff54b..a845dab580483 100644 --- a/libc/include/sys/sendfile.yaml +++ b/libc/include/sys/sendfile.yaml @@ -1,16 +1,8 @@ header: sys/sendfile.h -header_template: sendfile.h.def -macros: [] -types: - - type_name: ssize_t - - type_name: size_t - - type_name: off_t -enums: [] -objects: [] +standards: + - linux functions: - name: sendfile - standards: - - GNUExtensions return_type: ssize_t arguments: - type: int diff --git a/libc/include/sys/statvfs.h.def b/libc/include/sys/statvfs.h.def deleted file mode 100644 index f23c9a3d5b1f9..0000000000000 --- a/libc/include/sys/statvfs.h.def +++ /dev/null @@ -1,16 +0,0 @@ -//===-- POSIX header statvfs.h --------------------------------------------===// -// -// 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_LIBC_SYS_STATVFS_H -#define LLVM_LIBC_SYS_STATVFS_H - -#include <__llvm-libc-common.h> - -%%public_api() - -#endif // LLVM_LIBC_SYS_STATVFS_H diff --git a/libc/include/sys/statvfs.yaml b/libc/include/sys/statvfs.yaml index 8c1d254add37f..e083677beee89 100644 --- a/libc/include/sys/statvfs.yaml +++ b/libc/include/sys/statvfs.yaml @@ -1,23 +1,21 @@ header: sys/statvfs.h -header_template: statvfs.h.def -macros: [] +standards: + - posix types: - type_name: struct_statvfs - type_name: fsblkcnt_t - type_name: fsfilcnt_t -enums: [] -objects: [] functions: - name: fstatvfs standards: - - POSIX + - posix return_type: int arguments: - type: int - type: struct statvfs * - name: statvfs standards: - - POSIX + - posix return_type: int arguments: - type: const char *__restrict diff --git a/libc/include/sys/types.yaml b/libc/include/sys/types.yaml index 6fa0b448fcd38..a00429d3817e1 100644 --- a/libc/include/sys/types.yaml +++ b/libc/include/sys/types.yaml @@ -1,32 +1,28 @@ header: sys/types.h -header_template: types.h.def -standards: POSIX -macros: [] +standards: + - posix types: - - type_name: uid_t - - type_name: time_t - - type_name: pthread_t - - type_name: pthread_rwlock_t - - type_name: pthread_rwlockattr_t - - type_name: pthread_mutex_t - type_name: blkcnt_t - type_name: blksize_t - type_name: clockid_t - - type_name: ssize_t - - type_name: pthread_mutexattr_t - - type_name: ino_t - - type_name: pthread_once_t - - type_name: mode_t - type_name: dev_t - - type_name: pthread_attr_t - type_name: gid_t - - type_name: pid_t + - type_name: ino_t + - type_name: mode_t - type_name: nlink_t - - type_name: suseconds_t - type_name: off_t - - type_name: size_t - - type_name: pthread_key_t + - type_name: pid_t + - type_name: pthread_attr_t - type_name: pthread_condattr_t -enums: [] -objects: [] -functions: [] + - type_name: pthread_key_t + - type_name: pthread_mutex_t + - type_name: pthread_mutexattr_t + - type_name: pthread_once_t + - type_name: pthread_rwlock_t + - type_name: pthread_rwlockattr_t + - type_name: pthread_t + - type_name: size_t + - type_name: ssize_t + - type_name: suseconds_t + - type_name: time_t + - type_name: uid_t diff --git a/libc/include/sys/uio.h.def b/libc/include/sys/uio.h.def deleted file mode 100644 index 76496cb2310f7..0000000000000 --- a/libc/include/sys/uio.h.def +++ /dev/null @@ -1,16 +0,0 @@ -//===-- POSIX header uio.h ------------------------------------------------===// -// -// 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_LIBC_SYS_UIO_H -#define LLVM_LIBC_SYS_UIO_H - -#include "__llvm-libc-common.h" - -%%public_api() - -#endif // LLVM_LIBC_SYS_UIO_H diff --git a/libc/include/sys/uio.yaml b/libc/include/sys/uio.yaml index 6d3f336b2b520..929911e669386 100644 --- a/libc/include/sys/uio.yaml +++ b/libc/include/sys/uio.yaml @@ -1,15 +1,13 @@ header: sys/uio.h -header_template: uio.h.def -macros: [] +standards: + - posix types: - type_name: struct_iovec - type_name: ssize_t -enums: [] -objects: [] functions: - name: writev standards: - - POSIX + - posix return_type: ssize_t arguments: - type: int @@ -17,7 +15,7 @@ functions: - type: int - name: readv standards: - - POSIX + - posix return_type: ssize_t arguments: - type: int diff --git a/libc/include/sys/utsname.h.def b/libc/include/sys/utsname.h.def deleted file mode 100644 index 08dbbfc062453..0000000000000 --- a/libc/include/sys/utsname.h.def +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Linux sys/utsname.h -----------------------------------------------===// -// -// 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_LIBC_SYS_UTSNAME_H -#define LLVM_LIBC_SYS_UTSNAME_H - -#include "__llvm-libc-common.h" - -%%public_api() - -#endif // LLVM_LIBC_SYS_UTSNAME_H diff --git a/libc/include/sys/utsname.yaml b/libc/include/sys/utsname.yaml index 6c7cb71f9a34f..0f0e4cdb38952 100644 --- a/libc/include/sys/utsname.yaml +++ b/libc/include/sys/utsname.yaml @@ -1,14 +1,12 @@ header: sys/utsname.h -header_template: utsname.h.def -macros: [] +standards: + - posix types: - type_name: struct_utsname -enums: [] -objects: [] functions: - name: uname standards: - - POSIX + - posix return_type: int arguments: - type: struct utsname * diff --git a/libc/include/threads.h.def b/libc/include/threads.h.def deleted file mode 100644 index b114bea0ace34..0000000000000 --- a/libc/include/threads.h.def +++ /dev/null @@ -1,16 +0,0 @@ -//===-- C standard library header threads.h -------------------------------===// -// -// 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_LIBC_THREADS_H -#define LLVM_LIBC_THREADS_H - -#include "__llvm-libc-common.h" - -%%public_api() - -#endif // LLVM_LIBC_THREADS_H diff --git a/libc/include/threads.yaml b/libc/include/threads.yaml index 7014822f9251d..99b29f1815549 100644 --- a/libc/include/threads.yaml +++ b/libc/include/threads.yaml @@ -1,5 +1,6 @@ header: threads.h -header_template: threads.h.def +standards: + - stdc macros: - macro_name: ONCE_FLAG_INIT macro_value: '{0}' diff --git a/libc/include/uchar.yaml b/libc/include/uchar.yaml index 713919796762d..d0799e28ac9cb 100644 --- a/libc/include/uchar.yaml +++ b/libc/include/uchar.yaml @@ -1,14 +1,9 @@ header: uchar.h -header_template: uchar.h.def standards: - stdc -macros: [] types: - type_name: char32_t - type_name: char16_t - type_name: char8_t - type_name: mbstate_t - type_name: size_t -enums: [] -objects: [] -functions: [] diff --git a/libc/include/wctype.yaml b/libc/include/wctype.yaml new file mode 100644 index 0000000000000..fb4f96f7d17e4 --- /dev/null +++ b/libc/include/wctype.yaml @@ -0,0 +1,10 @@ +header: wctype.h +types: + - type_name: wint_t +functions: + - name: iswalpha + standards: + - stdc + return_type: int + arguments: + - type: wint_t diff --git a/libc/shared/math.h b/libc/shared/math.h index 3012cbb938816..e3c674c27ffaf 100644 --- a/libc/shared/math.h +++ b/libc/shared/math.h @@ -11,7 +11,16 @@ #include "libc_common.h" +#include "math/acos.h" +#include "math/acosf.h" +#include "math/acosf16.h" +#include "math/acoshf.h" +#include "math/acoshf16.h" +#include "math/erff.h" #include "math/exp.h" +#include "math/exp10.h" +#include "math/exp10f.h" +#include "math/exp10f16.h" #include "math/expf.h" #include "math/expf16.h" #include "math/frexpf.h" diff --git a/libc/shared/math/acos.h b/libc/shared/math/acos.h new file mode 100644 index 0000000000000..73c6b512e16f4 --- /dev/null +++ b/libc/shared/math/acos.h @@ -0,0 +1,23 @@ +//===-- Shared acos function ------------------------------------*- 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_LIBC_SHARED_MATH_ACOS_H +#define LLVM_LIBC_SHARED_MATH_ACOS_H + +#include "shared/libc_common.h" +#include "src/__support/math/acos.h" + +namespace LIBC_NAMESPACE_DECL { +namespace shared { + +using math::acos; + +} // namespace shared +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SHARED_MATH_ACOS_H diff --git a/libc/shared/math/acosf.h b/libc/shared/math/acosf.h new file mode 100644 index 0000000000000..7cdd64e7b379a --- /dev/null +++ b/libc/shared/math/acosf.h @@ -0,0 +1,23 @@ +//===-- Shared acosf function -----------------------------------*- 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_LIBC_SHARED_MATH_ACOSF_H +#define LLVM_LIBC_SHARED_MATH_ACOSF_H + +#include "shared/libc_common.h" +#include "src/__support/math/acosf.h" + +namespace LIBC_NAMESPACE_DECL { +namespace shared { + +using math::acosf; + +} // namespace shared +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SHARED_MATH_ACOSF_H diff --git a/libc/shared/math/acosf16.h b/libc/shared/math/acosf16.h new file mode 100644 index 0000000000000..aaf6ed9922556 --- /dev/null +++ b/libc/shared/math/acosf16.h @@ -0,0 +1,29 @@ +//===-- Shared acosf16 function ---------------------------------*- 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_LIBC_SHARED_MATH_ACOSF16_H +#define LLVM_LIBC_SHARED_MATH_ACOSF16_H + +#include "include/llvm-libc-macros/float16-macros.h" + +#ifdef LIBC_TYPES_HAS_FLOAT16 + +#include "shared/libc_common.h" +#include "src/__support/math/acosf16.h" + +namespace LIBC_NAMESPACE_DECL { +namespace shared { + +using math::acosf16; + +} // namespace shared +} // namespace LIBC_NAMESPACE_DECL + +#endif // LIBC_TYPES_HAS_FLOAT16 + +#endif // LLVM_LIBC_SHARED_MATH_ACOSF16_H diff --git a/libc/shared/math/acoshf.h b/libc/shared/math/acoshf.h new file mode 100644 index 0000000000000..86bdbce3d905c --- /dev/null +++ b/libc/shared/math/acoshf.h @@ -0,0 +1,23 @@ +//===-- Shared acoshf function ----------------------------------*- 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_LIBC_SHARED_MATH_ACOSHF_H +#define LLVM_LIBC_SHARED_MATH_ACOSHF_H + +#include "shared/libc_common.h" +#include "src/__support/math/acoshf.h" + +namespace LIBC_NAMESPACE_DECL { +namespace shared { + +using math::acoshf; + +} // namespace shared +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SHARED_MATH_ACOSHF_H diff --git a/libc/shared/math/acoshf16.h b/libc/shared/math/acoshf16.h new file mode 100644 index 0000000000000..2f0bc6e80ab6d --- /dev/null +++ b/libc/shared/math/acoshf16.h @@ -0,0 +1,29 @@ +//===-- Shared acoshf16 function --------------------------------*- 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_LIBC_SHARED_MATH_ACOSHF16_H +#define LLVM_LIBC_SHARED_MATH_ACOSHF16_H + +#include "include/llvm-libc-macros/float16-macros.h" +#include "shared/libc_common.h" + +#ifdef LIBC_TYPES_HAS_FLOAT16 + +#include "src/__support/math/acoshf16.h" + +namespace LIBC_NAMESPACE_DECL { +namespace shared { + +using math::acoshf16; + +} // namespace shared +} // namespace LIBC_NAMESPACE_DECL + +#endif // LIBC_TYPES_HAS_FLOAT16 + +#endif // LLVM_LIBC_SHARED_MATH_ACOSHF16_H diff --git a/libc/shared/math/erff.h b/libc/shared/math/erff.h new file mode 100644 index 0000000000000..d0cca15570988 --- /dev/null +++ b/libc/shared/math/erff.h @@ -0,0 +1,23 @@ +//===-- Shared erff function ------------------------------------*- 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_LIBC_SHARED_MATH_ERFF_H +#define LLVM_LIBC_SHARED_MATH_ERFF_H + +#include "shared/libc_common.h" +#include "src/__support/math/erff.h" + +namespace LIBC_NAMESPACE_DECL { +namespace shared { + +using math::erff; + +} // namespace shared +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SHARED_MATH_ERFF_H diff --git a/libc/shared/math/exp10.h b/libc/shared/math/exp10.h new file mode 100644 index 0000000000000..3d36d9103705f --- /dev/null +++ b/libc/shared/math/exp10.h @@ -0,0 +1,23 @@ +//===-- Shared exp10 function -----------------------------------*- 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_LIBC_SHARED_MATH_EXP10_H +#define LLVM_LIBC_SHARED_MATH_EXP10_H + +#include "shared/libc_common.h" +#include "src/__support/math/exp10.h" + +namespace LIBC_NAMESPACE_DECL { +namespace shared { + +using math::exp10; + +} // namespace shared +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SHARED_MATH_EXP10_H diff --git a/libc/shared/math/exp10f.h b/libc/shared/math/exp10f.h new file mode 100644 index 0000000000000..cd2ba54e6f4f2 --- /dev/null +++ b/libc/shared/math/exp10f.h @@ -0,0 +1,23 @@ +//===-- Shared exp10f function ----------------------------------*- 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_LIBC_SHARED_MATH_EXP10F_H +#define LLVM_LIBC_SHARED_MATH_EXP10F_H + +#include "shared/libc_common.h" +#include "src/__support/math/exp10f.h" + +namespace LIBC_NAMESPACE_DECL { +namespace shared { + +using math::exp10f; + +} // namespace shared +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SHARED_MATH_EXP10F_H diff --git a/libc/shared/math/exp10f16.h b/libc/shared/math/exp10f16.h new file mode 100644 index 0000000000000..af00787b058bc --- /dev/null +++ b/libc/shared/math/exp10f16.h @@ -0,0 +1,29 @@ +//===-- Shared exp10f16 function --------------------------------*- 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_LIBC_SHARED_MATH_EXP10F_H +#define LLVM_LIBC_SHARED_MATH_EXP10F_H + +#include "include/llvm-libc-macros/float16-macros.h" +#include "shared/libc_common.h" + +#ifdef LIBC_TYPES_HAS_FLOAT16 + +#include "src/__support/math/exp10f16.h" + +namespace LIBC_NAMESPACE_DECL { +namespace shared { + +using math::exp10f16; + +} // namespace shared +} // namespace LIBC_NAMESPACE_DECL + +#endif // LIBC_TYPES_HAS_FLOAT16 + +#endif // LLVM_LIBC_SHARED_MATH_EXP10F_H diff --git a/libc/shared/sign.h b/libc/shared/sign.h new file mode 100644 index 0000000000000..faa8648b96439 --- /dev/null +++ b/libc/shared/sign.h @@ -0,0 +1,23 @@ +//===-- Shared sign type ----------------------------------------*- 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_LIBC_SHARED_SIGN_H +#define LLVM_LIBC_SHARED_SIGN_H + +#include "libc_common.h" +#include "src/__support/sign.h" + +namespace LIBC_NAMESPACE_DECL { +namespace shared { + +using LIBC_NAMESPACE_DECL::Sign; + +} // namespace shared +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SHARED_SIGN_H diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt index a665253c4cc03..d7a1e1f49e6ff 100644 --- a/libc/src/CMakeLists.txt +++ b/libc/src/CMakeLists.txt @@ -17,6 +17,7 @@ add_subdirectory(strings) add_subdirectory(time) add_subdirectory(unistd) add_subdirectory(wchar) +add_subdirectory(wctype) if(${LIBC_TARGET_OS} STREQUAL "linux") add_subdirectory(dirent) diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt index cc941f23135a6..f157d90abb8aa 100644 --- a/libc/src/__support/FPUtil/CMakeLists.txt +++ b/libc/src/__support/FPUtil/CMakeLists.txt @@ -209,6 +209,17 @@ add_header_library( libc.src.__support.macros.properties.types ) +add_header_library( + comparison_operations + HDRS + comparison_operations.h + DEPENDS + .fenv_impl + .fp_bits + libc.src.__support.CPP.type_traits + libc.src.__support.macros.config +) + add_header_library( hypot HDRS diff --git a/libc/src/__support/FPUtil/PolyEval.h b/libc/src/__support/FPUtil/PolyEval.h index 41104620ed61d..7bec4e30a9960 100644 --- a/libc/src/__support/FPUtil/PolyEval.h +++ b/libc/src/__support/FPUtil/PolyEval.h @@ -37,7 +37,7 @@ LIBC_INLINE cpp::enable_if_t<(sizeof(T) <= sizeof(void *)), T> polyeval(T, } template -LIBC_INLINE cpp::enable_if_t<(sizeof(T) > sizeof(void *)), T> +LIBC_INLINE static constexpr cpp::enable_if_t<(sizeof(T) > sizeof(void *)), T> polyeval(const T &x, const T &a0, const Ts &...a) { return multiply_add(x, polyeval(x, a...), a0); } diff --git a/libc/src/__support/FPUtil/comparison_operations.h b/libc/src/__support/FPUtil/comparison_operations.h new file mode 100644 index 0000000000000..ff62ce085513b --- /dev/null +++ b/libc/src/__support/FPUtil/comparison_operations.h @@ -0,0 +1,114 @@ +//===-- Comparison operations on floating point numbers ---------*- 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_LIBC_SRC___SUPPORT_FPUTIL_COMPARISONOPERATIONS_H +#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_COMPARISONOPERATIONS_H + +#include "FEnvImpl.h" +#include "FPBits.h" +#include "src/__support/CPP/type_traits.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { +namespace fputil { + +// All predicates are hereby implemented as per IEEE Std 754-2019 +// Implements compareQuietEqual predicate +// Rules for comparison within the same floating point type +// 1. +0 = −0 +// 2. (i) +inf = +inf +// (ii) -inf = -inf +// (iii) -inf != +inf +// 3. Any comparison with NaN returns false +template +LIBC_INLINE cpp::enable_if_t, bool> equals(T x, + T y) { + using FPBits = FPBits; + FPBits x_bits(x); + FPBits y_bits(y); + + if (x_bits.is_signaling_nan() || y_bits.is_signaling_nan()) + fputil::raise_except_if_required(FE_INVALID); + + // NaN == x returns false for every x + if (x_bits.is_nan() || y_bits.is_nan()) + return false; + + // +/- 0 == +/- 0 + if (x_bits.is_zero() && y_bits.is_zero()) + return true; + + return x_bits.uintval() == y_bits.uintval(); +} + +// Implements compareSignalingLess predicate +// Section 5.11 Rules: +// 1. -inf < x (x != -inf) +// 2. x < +inf (x != +inf) +// 3. Any comparison with NaN return false +template +LIBC_INLINE cpp::enable_if_t, bool> less_than(T x, + T y) { + using FPBits = FPBits; + FPBits x_bits(x); + FPBits y_bits(y); + + // Any comparison with NaN returns false + if (x_bits.is_nan() || y_bits.is_nan()) { + fputil::raise_except_if_required(FE_INVALID); + return false; + } + + if (x_bits.is_zero() && y_bits.is_zero()) + return false; + + if (x_bits.is_neg() && y_bits.is_pos()) + return true; + + if (x_bits.is_pos() && y_bits.is_neg()) + return false; + + // since floating-point numbers are stored in the format: s | e | m + // we can directly compare the uintval's + + // both negative + if (x_bits.is_neg()) + return x_bits.uintval() > y_bits.uintval(); + + // both positive + return x_bits.uintval() < y_bits.uintval(); +} + +// Implements compareSignalingGreater predicate +// x < y => y > x +template +LIBC_INLINE cpp::enable_if_t, bool> +greater_than(T x, T y) { + return less_than(y, x); +} + +// Implements compareSignalingLessEqual predicate +// x <= y => (x < y) || (x == y) +template +LIBC_INLINE cpp::enable_if_t, bool> +less_than_or_equals(T x, T y) { + return less_than(x, y) || equals(x, y); +} + +// Implements compareSignalingGreaterEqual predicate +// x >= y => (x > y) || (x == y) => (y < x) || (x == y) +template +LIBC_INLINE cpp::enable_if_t, bool> +greater_than_or_equals(T x, T y) { + return less_than(y, x) || equals(x, y); +} + +} // namespace fputil +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_COMPARISONOPERATIONS_H diff --git a/libc/src/__support/FPUtil/double_double.h b/libc/src/__support/FPUtil/double_double.h index c27885aadc028..8e54e845de493 100644 --- a/libc/src/__support/FPUtil/double_double.h +++ b/libc/src/__support/FPUtil/double_double.h @@ -151,8 +151,8 @@ LIBC_INLINE DoubleDouble quick_mult(double a, const DoubleDouble &b) { } template -LIBC_INLINE DoubleDouble quick_mult(const DoubleDouble &a, - const DoubleDouble &b) { +LIBC_INLINE constexpr DoubleDouble quick_mult(const DoubleDouble &a, + const DoubleDouble &b) { DoubleDouble r = exact_mult(a.hi, b.hi); double t1 = multiply_add(a.hi, b.lo, r.lo); double t2 = multiply_add(a.lo, b.hi, t1); diff --git a/libc/src/__support/macros/properties/architectures.h b/libc/src/__support/macros/properties/architectures.h index c88956ff41148..ecc93196be286 100644 --- a/libc/src/__support/macros/properties/architectures.h +++ b/libc/src/__support/macros/properties/architectures.h @@ -21,7 +21,7 @@ #define LIBC_TARGET_ARCH_IS_GPU #endif -#if defined(__pnacl__) || defined(__CLR_VER) || defined(LIBC_TARGET_ARCH_IS_GPU) +#if defined(__CLR_VER) || defined(LIBC_TARGET_ARCH_IS_GPU) #define LIBC_TARGET_ARCH_IS_VM #endif diff --git a/libc/src/__support/macros/properties/cpu_features.h b/libc/src/__support/macros/properties/cpu_features.h index cdb2df97b2b9a..fde30eadfd83b 100644 --- a/libc/src/__support/macros/properties/cpu_features.h +++ b/libc/src/__support/macros/properties/cpu_features.h @@ -81,7 +81,7 @@ #endif #if defined(__ARM_FEATURE_FMA) || (defined(__AVX2__) && defined(__FMA__)) || \ - defined(__NVPTX__) || defined(__AMDGPU__) || defined(__LIBC_RISCV_USE_FMA) + defined(__NVPTX__) || defined(__AMDGPU__) || defined(__riscv_flen) #define LIBC_TARGET_CPU_HAS_FMA // Provide a more fine-grained control of FMA instruction for ARM targets. #if defined(LIBC_TARGET_CPU_HAS_FPU_HALF) diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt index f7ef9e7694fe6..9a8a4d16a4a0e 100644 --- a/libc/src/__support/math/CMakeLists.txt +++ b/libc/src/__support/math/CMakeLists.txt @@ -1,3 +1,126 @@ +add_header_library( + acos + HDRS + acos.h + DEPENDS + .asin_utils + libc.src.__support.math.asin_utils + libc.src.__support.FPUtil.double_double + libc.src.__support.FPUtil.dyadic_float + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.multiply_add + libc.src.__support.FPUtil.polyeval + libc.src.__support.FPUtil.sqrt + libc.src.__support.macros.optimization + libc.src.__support.macros.properties.types + libc.src.__support.macros.properties.cpu_features +) + +add_header_library( + acosf + HDRS + acosf.h + DEPENDS + .inv_trigf_utils + libc.src.__support.FPUtil.except_value_utils + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.multiply_add + libc.src.__support.FPUtil.polyeval + libc.src.__support.FPUtil.sqrt + libc.src.__support.macros.optimization +) + +add_header_library( + acosf16 + HDRS + acosf16.h + DEPENDS + libc.src.__support.FPUtil.cast + libc.src.__support.FPUtil.except_value_utils + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.multiply_add + libc.src.__support.FPUtil.polyeval + libc.src.__support.FPUtil.sqrt + libc.src.__support.macros.optimization + libc.src.__support.macros.properties.types +) + +add_header_library( + acosh_float_constants + HDRS + acosh_float_constants.h + DEPENDS + libc.src.__support.macros.config +) + +add_header_library( + acoshf_utils + HDRS + acoshf_utils.h + DEPENDS + .acosh_float_constants + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.multiply_add + libc.src.__support.FPUtil.polyeval +) + +add_header_library( + acoshf + HDRS + acoshf.h + DEPENDS + .acoshf_utils + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.multiply_add + libc.src.__support.FPUtil.sqrt + libc.src.__support.macros.optimization +) + +add_header_library( + acoshf16 + HDRS + acoshf16.h + DEPENDS + .acoshf_utils + libc.src.__support.FPUtil.cast + libc.src.__support.FPUtil.except_value_utils + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.multiply_add + libc.src.__support.FPUtil.polyeval + libc.src.__support.FPUtil.sqrt + libc.src.__support.macros.optimization +) + +add_header_library( + asin_utils + HDRS + asin_utils.h + DEPENDS + libc.src.__support.integer_literals + libc.src.__support.FPUtil.double_double + libc.src.__support.FPUtil.dyadic_float + libc.src.__support.FPUtil.multiply_add + libc.src.__support.FPUtil.nearest_integer + libc.src.__support.FPUtil.polyeval + libc.src.__support.macros.optimization +) + +add_header_library( + erff + HDRS + erff.h + DEPENDS + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.except_value_utils + libc.src.__support.FPUtil.multiply_add + libc.src.__support.FPUtil.polyeval + libc.src.__support.macros.optimization +) + add_header_library( exp_float_constants HDRS @@ -65,6 +188,16 @@ add_header_library( libc.src.__support.FPUtil.manipulation_functions ) +add_header_library( + inv_trigf_utils + HDRS + inv_trigf_utils.h + DEPENDS + libc.src.__support.FPUtil.multiply_add + libc.src.__support.FPUtil.polyeval + libc.src.__support.common +) + add_header_library( frexpf16 HDRS @@ -149,3 +282,86 @@ add_header_library( libc.src.__support.integer_literals libc.src.__support.macros.optimization ) + +add_header_library( + exp10 + HDRS + exp10.h + DEPENDS + .exp_constants + .exp_utils + libc.src.__support.CPP.bit + libc.src.__support.CPP.optional + libc.src.__support.FPUtil.dyadic_float + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.multiply_add + libc.src.__support.FPUtil.nearest_integer + libc.src.__support.FPUtil.polyeval + libc.src.__support.FPUtil.rounding_mode + libc.src.__support.FPUtil.triple_double + libc.src.__support.integer_literals + libc.src.__support.macros.optimization +) + +add_header_library( + exp10f_utils + HDRS + exp10f_utils.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.FPUtil.multiply_add + libc.src.__support.FPUtil.nearest_integer + libc.src.__support.FPUtil.polyeval + libc.src.__support.common + libc.src.__support.math.exp_utils +) + +add_header_library( + exp10f + HDRS + exp10f.h + DEPENDS + .exp10f_utils + libc.src.__support.macros.config + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.multiply_add + libc.src.__support.FPUtil.rounding_mode + libc.src.__support.macros.optimization +) + +add_header_library( + exp10_float16_constants + HDRS + exp10_float16_constants.h + DEPENDS + libc.src.__support.CPP.array +) + +add_header_library( + exp10f16_utils + HDRS + exp10f16_utils.h + DEPENDS + .expf16_utils + .exp10_float16_constants + libc.src.__support.FPUtil.fp_bits +) + +add_header_library( + exp10f16 + HDRS + exp10f16.h + DEPENDS + .exp10f16_utils + libc.src.__support.FPUtil.fp_bits + src.__support.FPUtil.FEnvImpl + src.__support.FPUtil.FPBits + src.__support.FPUtil.cast + src.__support.FPUtil.rounding_mode + src.__support.FPUtil.except_value_utils + src.__support.macros.optimization + src.__support.macros.properties.cpu_features +) diff --git a/libc/src/__support/math/acos.h b/libc/src/__support/math/acos.h new file mode 100644 index 0000000000000..a52ead7fc1b3b --- /dev/null +++ b/libc/src/__support/math/acos.h @@ -0,0 +1,284 @@ +//===-- Implementation header for acos --------------------------*- 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_LIBC_SRC___SUPPORT_MATH_ACOS_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_ACOS_H + +#include "asin_utils.h" +#include "src/__support/FPUtil/FEnvImpl.h" +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/double_double.h" +#include "src/__support/FPUtil/dyadic_float.h" +#include "src/__support/FPUtil/multiply_add.h" +#include "src/__support/FPUtil/sqrt.h" +#include "src/__support/macros/config.h" +#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY +#include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA + +namespace LIBC_NAMESPACE_DECL { + +namespace math { + +static constexpr double acos(double x) { + using DoubleDouble = fputil::DoubleDouble; + using namespace asin_internal; + using FPBits = fputil::FPBits; + + FPBits xbits(x); + int x_exp = xbits.get_biased_exponent(); + + // |x| < 0.5. + if (x_exp < FPBits::EXP_BIAS - 1) { + // |x| < 2^-55. + if (LIBC_UNLIKELY(x_exp < FPBits::EXP_BIAS - 55)) { + // When |x| < 2^-55, acos(x) = pi/2 +#if defined(LIBC_MATH_HAS_SKIP_ACCURATE_PASS) + return PI_OVER_TWO.hi; +#else + // Force the evaluation and prevent constant propagation so that it + // is rounded correctly for FE_UPWARD rounding mode. + return (xbits.abs().get_val() + 0x1.0p-160) + PI_OVER_TWO.hi; +#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS + } + +#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS + // acos(x) = pi/2 - asin(x) + // = pi/2 - x * P(x^2) + double p = asin_eval(x * x); + return PI_OVER_TWO.hi + fputil::multiply_add(-x, p, PI_OVER_TWO.lo); +#else + unsigned idx = 0; + DoubleDouble x_sq = fputil::exact_mult(x, x); + double err = xbits.abs().get_val() * 0x1.0p-51; + // Polynomial approximation: + // p ~ asin(x)/x + DoubleDouble p = asin_eval(x_sq, idx, err); + // asin(x) ~ x * p + DoubleDouble r0 = fputil::exact_mult(x, p.hi); + // acos(x) = pi/2 - asin(x) + // ~ pi/2 - x * p + // = pi/2 - x * (p.hi + p.lo) + double r_hi = fputil::multiply_add(-x, p.hi, PI_OVER_TWO.hi); + // Use Dekker's 2SUM algorithm to compute the lower part. + double r_lo = ((PI_OVER_TWO.hi - r_hi) - r0.hi) - r0.lo; + r_lo = fputil::multiply_add(-x, p.lo, r_lo + PI_OVER_TWO.lo); + + // Ziv's accuracy test. + + double r_upper = r_hi + (r_lo + err); + double r_lower = r_hi + (r_lo - err); + + if (LIBC_LIKELY(r_upper == r_lower)) + return r_upper; + + // Ziv's accuracy test failed, perform 128-bit calculation. + + // Recalculate mod 1/64. + idx = static_cast(fputil::nearest_integer(x_sq.hi * 0x1.0p6)); + + // Get x^2 - idx/64 exactly. When FMA is available, double-double + // multiplication will be correct for all rounding modes. Otherwise we use + // Float128 directly. + Float128 x_f128(x); + +#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE + // u = x^2 - idx/64 + Float128 u_hi( + fputil::multiply_add(static_cast(idx), -0x1.0p-6, x_sq.hi)); + Float128 u = fputil::quick_add(u_hi, Float128(x_sq.lo)); +#else + Float128 x_sq_f128 = fputil::quick_mul(x_f128, x_f128); + Float128 u = fputil::quick_add( + x_sq_f128, Float128(static_cast(idx) * (-0x1.0p-6))); +#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE + + Float128 p_f128 = asin_eval(u, idx); + // Flip the sign of x_f128 to perform subtraction. + x_f128.sign = x_f128.sign.negate(); + Float128 r = + fputil::quick_add(PI_OVER_TWO_F128, fputil::quick_mul(x_f128, p_f128)); + + return static_cast(r); +#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS + } + // |x| >= 0.5 + + double x_abs = xbits.abs().get_val(); + + // Maintaining the sign: + constexpr double SIGN[2] = {1.0, -1.0}; + double x_sign = SIGN[xbits.is_neg()]; + // |x| >= 1 + if (LIBC_UNLIKELY(x_exp >= FPBits::EXP_BIAS)) { + // x = +-1, asin(x) = +- pi/2 + if (x_abs == 1.0) { + // x = 1, acos(x) = 0, + // x = -1, acos(x) = pi + return x == 1.0 ? 0.0 : fputil::multiply_add(-x_sign, PI.hi, PI.lo); + } + // |x| > 1, return NaN. + if (xbits.is_quiet_nan()) + return x; + + // Set domain error for non-NaN input. + if (!xbits.is_nan()) + fputil::set_errno_if_required(EDOM); + + fputil::raise_except_if_required(FE_INVALID); + return FPBits::quiet_nan().get_val(); + } + + // When |x| >= 0.5, we perform range reduction as follow: + // + // When 0.5 <= x < 1, let: + // y = acos(x) + // We will use the double angle formula: + // cos(2y) = 1 - 2 sin^2(y) + // and the complement angle identity: + // x = cos(y) = 1 - 2 sin^2 (y/2) + // So: + // sin(y/2) = sqrt( (1 - x)/2 ) + // And hence: + // y/2 = asin( sqrt( (1 - x)/2 ) ) + // Equivalently: + // acos(x) = y = 2 * asin( sqrt( (1 - x)/2 ) ) + // Let u = (1 - x)/2, then: + // acos(x) = 2 * asin( sqrt(u) ) + // Moreover, since 0.5 <= x < 1: + // 0 < u <= 1/4, and 0 < sqrt(u) <= 0.5, + // And hence we can reuse the same polynomial approximation of asin(x) when + // |x| <= 0.5: + // acos(x) ~ 2 * sqrt(u) * P(u). + // + // When -1 < x <= -0.5, we reduce to the previous case using the formula: + // acos(x) = pi - acos(-x) + // = pi - 2 * asin ( sqrt( (1 + x)/2 ) ) + // ~ pi - 2 * sqrt(u) * P(u), + // where u = (1 - |x|)/2. + + // u = (1 - |x|)/2 + double u = fputil::multiply_add(x_abs, -0.5, 0.5); + // v_hi + v_lo ~ sqrt(u). + // Let: + // h = u - v_hi^2 = (sqrt(u) - v_hi) * (sqrt(u) + v_hi) + // Then: + // sqrt(u) = v_hi + h / (sqrt(u) + v_hi) + // ~ v_hi + h / (2 * v_hi) + // So we can use: + // v_lo = h / (2 * v_hi). + double v_hi = fputil::sqrt(u); + +#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS + constexpr DoubleDouble CONST_TERM[2] = {{0.0, 0.0}, PI}; + DoubleDouble const_term = CONST_TERM[xbits.is_neg()]; + + double p = asin_eval(u); + double scale = x_sign * 2.0 * v_hi; + double r = const_term.hi + fputil::multiply_add(scale, p, const_term.lo); + return r; +#else + +#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE + double h = fputil::multiply_add(v_hi, -v_hi, u); +#else + DoubleDouble v_hi_sq = fputil::exact_mult(v_hi, v_hi); + double h = (u - v_hi_sq.hi) - v_hi_sq.lo; +#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE + + // Scale v_lo and v_hi by 2 from the formula: + // vh = v_hi * 2 + // vl = 2*v_lo = h / v_hi. + double vh = v_hi * 2.0; + double vl = h / v_hi; + + // Polynomial approximation: + // p ~ asin(sqrt(u))/sqrt(u) + unsigned idx = 0; + double err = vh * 0x1.0p-51; + + DoubleDouble p = asin_eval(DoubleDouble{0.0, u}, idx, err); + + // Perform computations in double-double arithmetic: + // asin(x) = pi/2 - (v_hi + v_lo) * (ASIN_COEFFS[idx][0] + p) + DoubleDouble r0 = fputil::quick_mult(DoubleDouble{vl, vh}, p); + + double r_hi = 0, r_lo = 0; + if (xbits.is_pos()) { + r_hi = r0.hi; + r_lo = r0.lo; + } else { + DoubleDouble r = fputil::exact_add(PI.hi, -r0.hi); + r_hi = r.hi; + r_lo = (PI.lo - r0.lo) + r.lo; + } + + // Ziv's accuracy test. + + double r_upper = r_hi + (r_lo + err); + double r_lower = r_hi + (r_lo - err); + + if (LIBC_LIKELY(r_upper == r_lower)) + return r_upper; + + // Ziv's accuracy test failed, we redo the computations in Float128. + // Recalculate mod 1/64. + idx = static_cast(fputil::nearest_integer(u * 0x1.0p6)); + + // After the first step of Newton-Raphson approximating v = sqrt(u), we have + // that: + // sqrt(u) = v_hi + h / (sqrt(u) + v_hi) + // v_lo = h / (2 * v_hi) + // With error: + // sqrt(u) - (v_hi + v_lo) = h * ( 1/(sqrt(u) + v_hi) - 1/(2*v_hi) ) + // = -h^2 / (2*v * (sqrt(u) + v)^2). + // Since: + // (sqrt(u) + v_hi)^2 ~ (2sqrt(u))^2 = 4u, + // we can add another correction term to (v_hi + v_lo) that is: + // v_ll = -h^2 / (2*v_hi * 4u) + // = -v_lo * (h / 4u) + // = -vl * (h / 8u), + // making the errors: + // sqrt(u) - (v_hi + v_lo + v_ll) = O(h^3) + // well beyond 128-bit precision needed. + + // Get the rounding error of vl = 2 * v_lo ~ h / vh + // Get full product of vh * vl +#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE + double vl_lo = fputil::multiply_add(-v_hi, vl, h) / v_hi; +#else + DoubleDouble vh_vl = fputil::exact_mult(v_hi, vl); + double vl_lo = ((h - vh_vl.hi) - vh_vl.lo) / v_hi; +#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE + // vll = 2*v_ll = -vl * (h / (4u)). + double t = h * (-0.25) / u; + double vll = fputil::multiply_add(vl, t, vl_lo); + // m_v = -(v_hi + v_lo + v_ll). + Float128 m_v = fputil::quick_add( + Float128(vh), fputil::quick_add(Float128(vl), Float128(vll))); + m_v.sign = xbits.sign(); + + // Perform computations in Float128: + // acos(x) = (v_hi + v_lo + vll) * P(u) , when 0.5 <= x < 1, + // = pi - (v_hi + v_lo + vll) * P(u) , when -1 < x <= -0.5. + Float128 y_f128(fputil::multiply_add(static_cast(idx), -0x1.0p-6, u)); + + Float128 p_f128 = asin_eval(y_f128, idx); + Float128 r_f128 = fputil::quick_mul(m_v, p_f128); + + if (xbits.is_neg()) + r_f128 = fputil::quick_add(PI_F128, r_f128); + + return static_cast(r_f128); +#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS +} + +} // namespace math + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ACOS_H diff --git a/libc/src/__support/math/acosf.h b/libc/src/__support/math/acosf.h new file mode 100644 index 0000000000000..153087e998211 --- /dev/null +++ b/libc/src/__support/math/acosf.h @@ -0,0 +1,147 @@ +//===-- Implementation header for acosf -------------------------*- 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_LIBC_SRC___SUPPORT_MATH_ACOSF_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_ACOSF_H + +#include "inv_trigf_utils.h" +#include "src/__support/FPUtil/FEnvImpl.h" +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/except_value_utils.h" +#include "src/__support/FPUtil/multiply_add.h" +#include "src/__support/FPUtil/sqrt.h" +#include "src/__support/macros/config.h" +#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY + +namespace LIBC_NAMESPACE_DECL { + +namespace math { + +namespace acosf_internal { + +#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS + +static constexpr size_t N_EXCEPTS = 4; + +// Exceptional values when |x| <= 0.5 +static constexpr fputil::ExceptValues ACOSF_EXCEPTS = {{ + // (inputs, RZ output, RU offset, RD offset, RN offset) + // x = 0x1.110b46p-26, acosf(x) = 0x1.921fb4p0 (RZ) + {0x328885a3, 0x3fc90fda, 1, 0, 1}, + // x = -0x1.110b46p-26, acosf(x) = 0x1.921fb4p0 (RZ) + {0xb28885a3, 0x3fc90fda, 1, 0, 1}, + // x = 0x1.04c444p-12, acosf(x) = 0x1.920f68p0 (RZ) + {0x39826222, 0x3fc907b4, 1, 0, 1}, + // x = -0x1.04c444p-12, acosf(x) = 0x1.923p0 (RZ) + {0xb9826222, 0x3fc91800, 1, 0, 1}, +}}; + +#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS + +} // namespace acosf_internal + +static constexpr float acosf(float x) { + using namespace acosf_internal; + using namespace inv_trigf_utils_internal; + using FPBits = typename fputil::FPBits; + + FPBits xbits(x); + uint32_t x_uint = xbits.uintval(); + uint32_t x_abs = xbits.uintval() & 0x7fff'ffffU; + uint32_t x_sign = x_uint >> 31; + + // |x| <= 0.5 + if (LIBC_UNLIKELY(x_abs <= 0x3f00'0000U)) { + // |x| < 0x1p-10 + if (LIBC_UNLIKELY(x_abs < 0x3a80'0000U)) { + // When |x| < 2^-10, we use the following approximation: + // acos(x) = pi/2 - asin(x) + // ~ pi/2 - x - x^3 / 6 + +#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS + // Check for exceptional values + if (auto r = ACOSF_EXCEPTS.lookup(x_uint); LIBC_UNLIKELY(r.has_value())) + return r.value(); +#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS + + double xd = static_cast(x); + return static_cast(fputil::multiply_add( + -0x1.5555555555555p-3 * xd, xd * xd, M_MATH_PI_2 - xd)); + } + + // For |x| <= 0.5, we approximate acosf(x) by: + // acos(x) = pi/2 - asin(x) = pi/2 - x * P(x^2) + // Where P(X^2) = Q(X) is a degree-20 minimax even polynomial approximating + // asin(x)/x on [0, 0.5] generated by Sollya with: + // > Q = fpminimax(asin(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20|], + // [|1, D...|], [0, 0.5]); + double xd = static_cast(x); + double xsq = xd * xd; + double x3 = xd * xsq; + double r = asin_eval(xsq); + return static_cast(fputil::multiply_add(-x3, r, M_MATH_PI_2 - xd)); + } + + // |x| >= 1, return 0, 2pi, or NaNs. + if (LIBC_UNLIKELY(x_abs >= 0x3f80'0000U)) { + if (x_abs == 0x3f80'0000U) + return x_sign ? /* x == -1.0f */ fputil::round_result_slightly_down( + 0x1.921fb6p+1f) + : /* x == 1.0f */ 0.0f; + + if (xbits.is_signaling_nan()) { + fputil::raise_except_if_required(FE_INVALID); + return FPBits::quiet_nan().get_val(); + } + + // |x| <= +/-inf + if (x_abs <= 0x7f80'0000U) { + fputil::set_errno_if_required(EDOM); + fputil::raise_except_if_required(FE_INVALID); + } + + return x + FPBits::quiet_nan().get_val(); + } + + // When 0.5 < |x| < 1, we perform range reduction as follow: + // + // Assume further that 0.5 < x <= 1, and let: + // y = acos(x) + // We use the double angle formula: + // x = cos(y) = 1 - 2 sin^2(y/2) + // So: + // sin(y/2) = sqrt( (1 - x)/2 ) + // And hence: + // y = 2 * asin( sqrt( (1 - x)/2 ) ) + // Let u = (1 - x)/2, then + // acos(x) = 2 * asin( sqrt(u) ) + // Moreover, since 0.5 < x <= 1, + // 0 <= u < 1/4, and 0 <= sqrt(u) < 0.5, + // And hence we can reuse the same polynomial approximation of asin(x) when + // |x| <= 0.5: + // acos(x) ~ 2 * sqrt(u) * P(u). + // + // When -1 < x <= -0.5, we use the identity: + // acos(x) = pi - acos(-x) + // which is reduced to the postive case. + + xbits.set_sign(Sign::POS); + double xd = static_cast(xbits.get_val()); + double u = fputil::multiply_add(-0.5, xd, 0.5); + double cv = 2 * fputil::sqrt(u); + + double r3 = asin_eval(u); + double r = fputil::multiply_add(cv * u, r3, cv); + return static_cast(x_sign ? M_MATH_PI - r : r); +} + +} // namespace math + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ACOS_H diff --git a/libc/src/__support/math/acosf16.h b/libc/src/__support/math/acosf16.h new file mode 100644 index 0000000000000..58d3761b95245 --- /dev/null +++ b/libc/src/__support/math/acosf16.h @@ -0,0 +1,164 @@ +//===-- Implementation header for acosf16 -----------------------*- 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_LIBC_SRC___SUPPORT_MATH_ACOSF16_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_ACOSF16_H + +#include "include/llvm-libc-macros/float16-macros.h" + +#ifdef LIBC_TYPES_HAS_FLOAT16 + +#include "src/__support/FPUtil/FEnvImpl.h" +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/PolyEval.h" +#include "src/__support/FPUtil/cast.h" +#include "src/__support/FPUtil/except_value_utils.h" +#include "src/__support/FPUtil/multiply_add.h" +#include "src/__support/FPUtil/sqrt.h" +#include "src/__support/macros/optimization.h" + +namespace LIBC_NAMESPACE_DECL { + +namespace math { + +static constexpr float16 acosf16(float16 x) { + + // Generated by Sollya using the following command: + // > round(pi/2, SG, RN); + // > round(pi, SG, RN); + constexpr float PI_OVER_2 = 0x1.921fb6p0f; + constexpr float PI = 0x1.921fb6p1f; + +#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS + constexpr size_t N_EXCEPTS = 2; + + constexpr fputil::ExceptValues ACOSF16_EXCEPTS{{ + // (input, RZ output, RU offset, RD offset, RN offset) + {0xacaf, 0x3e93, 1, 0, 0}, + {0xb874, 0x4052, 1, 0, 1}, + }}; +#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS + + using FPBits = fputil::FPBits; + FPBits xbits(x); + + uint16_t x_u = xbits.uintval(); + uint16_t x_abs = x_u & 0x7fff; + uint16_t x_sign = x_u >> 15; + + // |x| > 0x1p0, |x| > 1, or x is NaN. + if (LIBC_UNLIKELY(x_abs > 0x3c00)) { + // acosf16(NaN) = NaN + if (xbits.is_nan()) { + if (xbits.is_signaling_nan()) { + fputil::raise_except_if_required(FE_INVALID); + return FPBits::quiet_nan().get_val(); + } + + return x; + } + + // 1 < |x| <= +/-inf + fputil::raise_except_if_required(FE_INVALID); + fputil::set_errno_if_required(EDOM); + + return FPBits::quiet_nan().get_val(); + } + + float xf = x; + +#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS + // Handle exceptional values + if (auto r = ACOSF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value())) + return r.value(); +#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS + + // |x| == 0x1p0, x is 1 or -1 + // if x is (-)1, return pi, else + // if x is (+)1, return 0 + if (LIBC_UNLIKELY(x_abs == 0x3c00)) + return fputil::cast(x_sign ? PI : 0.0f); + + float xsq = xf * xf; + + // |x| <= 0x1p-1, |x| <= 0.5 + if (x_abs <= 0x3800) { + // if x is 0, return pi/2 + if (LIBC_UNLIKELY(x_abs == 0)) + return fputil::cast(PI_OVER_2); + + // Note that: acos(x) = pi/2 + asin(-x) = pi/2 - asin(x) + // Degree-6 minimax polynomial of asin(x) generated by Sollya with: + // > P = fpminimax(asin(x)/x, [|0, 2, 4, 6, 8|], [|SG...|], [0, 0.5]); + float interm = + fputil::polyeval(xsq, 0x1.000002p0f, 0x1.554c2ap-3f, 0x1.3541ccp-4f, + 0x1.43b2d6p-5f, 0x1.a0d73ep-5f); + return fputil::cast(fputil::multiply_add(-xf, interm, PI_OVER_2)); + } + + // When |x| > 0.5, assume that 0.5 < |x| <= 1 + // + // Step-by-step range-reduction proof: + // 1: Let y = asin(x), such that, x = sin(y) + // 2: From complimentary angle identity: + // x = sin(y) = cos(pi/2 - y) + // 3: Let z = pi/2 - y, such that x = cos(z) + // 4: From double angle formula; cos(2A) = 1 - 2 * sin^2(A): + // z = 2A, z/2 = A + // cos(z) = 1 - 2 * sin^2(z/2) + // 5: Make sin(z/2) subject of the formula: + // sin(z/2) = sqrt((1 - cos(z))/2) + // 6: Recall [3]; x = cos(z). Therefore: + // sin(z/2) = sqrt((1 - x)/2) + // 7: Let u = (1 - x)/2 + // 8: Therefore: + // asin(sqrt(u)) = z/2 + // 2 * asin(sqrt(u)) = z + // 9: Recall [3]; z = pi/2 - y. Therefore: + // y = pi/2 - z + // y = pi/2 - 2 * asin(sqrt(u)) + // 10: Recall [1], y = asin(x). Therefore: + // asin(x) = pi/2 - 2 * asin(sqrt(u)) + // 11: Recall that: acos(x) = pi/2 + asin(-x) = pi/2 - asin(x) + // Therefore: + // acos(x) = pi/2 - (pi/2 - 2 * asin(sqrt(u))) + // acos(x) = 2 * asin(sqrt(u)) + // + // THE RANGE REDUCTION, HOW? + // 12: Recall [7], u = (1 - x)/2 + // 13: Since 0.5 < x <= 1, therefore: + // 0 <= u <= 0.25 and 0 <= sqrt(u) <= 0.5 + // + // Hence, we can reuse the same [0, 0.5] domain polynomial approximation for + // Step [11] as `sqrt(u)` is in range. + // When -1 < x <= -0.5, the identity: + // acos(x) = pi - acos(-x) + // allows us to compute for the negative x value (lhs) + // with a positive x value instead (rhs). + + float xf_abs = (xf < 0 ? -xf : xf); + float u = fputil::multiply_add(-0.5f, xf_abs, 0.5f); + float sqrt_u = fputil::sqrt(u); + + // Degree-6 minimax polynomial of asin(x) generated by Sollya with: + // > P = fpminimax(asin(x)/x, [|0, 2, 4, 6, 8|], [|SG...|], [0, 0.5]); + float asin_sqrt_u = + sqrt_u * fputil::polyeval(u, 0x1.000002p0f, 0x1.554c2ap-3f, + 0x1.3541ccp-4f, 0x1.43b2d6p-5f, 0x1.a0d73ep-5f); + + return fputil::cast( + x_sign ? fputil::multiply_add(-2.0f, asin_sqrt_u, PI) : 2 * asin_sqrt_u); +} + +} // namespace math + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LIBC_TYPES_HAS_FLOAT16 + +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ACOS_H diff --git a/libc/src/__support/math/acosh_float_constants.h b/libc/src/__support/math/acosh_float_constants.h new file mode 100644 index 0000000000000..2eb245d8265e0 --- /dev/null +++ b/libc/src/__support/math/acosh_float_constants.h @@ -0,0 +1,114 @@ +//===-- Common constants for acoshf function --------------------*- 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_LIBC_SRC___SUPPORT_MATH_ACOSH_FLOAT_CONSTANTS_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_ACOSH_FLOAT_CONSTANTS_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +namespace acoshf_internal { + +// Lookup table for (1/f) where f = 1 + n*2^(-7), n = 0..127. +static constexpr double ONE_OVER_F[128] = { + 0x1.0000000000000p+0, 0x1.fc07f01fc07f0p-1, 0x1.f81f81f81f820p-1, + 0x1.f44659e4a4271p-1, 0x1.f07c1f07c1f08p-1, 0x1.ecc07b301ecc0p-1, + 0x1.e9131abf0b767p-1, 0x1.e573ac901e574p-1, 0x1.e1e1e1e1e1e1ep-1, + 0x1.de5d6e3f8868ap-1, 0x1.dae6076b981dbp-1, 0x1.d77b654b82c34p-1, + 0x1.d41d41d41d41dp-1, 0x1.d0cb58f6ec074p-1, 0x1.cd85689039b0bp-1, + 0x1.ca4b3055ee191p-1, 0x1.c71c71c71c71cp-1, 0x1.c3f8f01c3f8f0p-1, + 0x1.c0e070381c0e0p-1, 0x1.bdd2b899406f7p-1, 0x1.bacf914c1bad0p-1, + 0x1.b7d6c3dda338bp-1, 0x1.b4e81b4e81b4fp-1, 0x1.b2036406c80d9p-1, + 0x1.af286bca1af28p-1, 0x1.ac5701ac5701bp-1, 0x1.a98ef606a63bep-1, + 0x1.a6d01a6d01a6dp-1, 0x1.a41a41a41a41ap-1, 0x1.a16d3f97a4b02p-1, + 0x1.9ec8e951033d9p-1, 0x1.9c2d14ee4a102p-1, 0x1.999999999999ap-1, + 0x1.970e4f80cb872p-1, 0x1.948b0fcd6e9e0p-1, 0x1.920fb49d0e229p-1, + 0x1.8f9c18f9c18fap-1, 0x1.8d3018d3018d3p-1, 0x1.8acb90f6bf3aap-1, + 0x1.886e5f0abb04ap-1, 0x1.8618618618618p-1, 0x1.83c977ab2beddp-1, + 0x1.8181818181818p-1, 0x1.7f405fd017f40p-1, 0x1.7d05f417d05f4p-1, + 0x1.7ad2208e0ecc3p-1, 0x1.78a4c8178a4c8p-1, 0x1.767dce434a9b1p-1, + 0x1.745d1745d1746p-1, 0x1.724287f46debcp-1, 0x1.702e05c0b8170p-1, + 0x1.6e1f76b4337c7p-1, 0x1.6c16c16c16c17p-1, 0x1.6a13cd1537290p-1, + 0x1.6816816816817p-1, 0x1.661ec6a5122f9p-1, 0x1.642c8590b2164p-1, + 0x1.623fa77016240p-1, 0x1.6058160581606p-1, 0x1.5e75bb8d015e7p-1, + 0x1.5c9882b931057p-1, 0x1.5ac056b015ac0p-1, 0x1.58ed2308158edp-1, + 0x1.571ed3c506b3ap-1, 0x1.5555555555555p-1, 0x1.5390948f40febp-1, + 0x1.51d07eae2f815p-1, 0x1.5015015015015p-1, 0x1.4e5e0a72f0539p-1, + 0x1.4cab88725af6ep-1, 0x1.4afd6a052bf5bp-1, 0x1.49539e3b2d067p-1, + 0x1.47ae147ae147bp-1, 0x1.460cbc7f5cf9ap-1, 0x1.446f86562d9fbp-1, + 0x1.42d6625d51f87p-1, 0x1.4141414141414p-1, 0x1.3fb013fb013fbp-1, + 0x1.3e22cbce4a902p-1, 0x1.3c995a47babe7p-1, 0x1.3b13b13b13b14p-1, + 0x1.3991c2c187f63p-1, 0x1.3813813813814p-1, 0x1.3698df3de0748p-1, + 0x1.3521cfb2b78c1p-1, 0x1.33ae45b57bcb2p-1, 0x1.323e34a2b10bfp-1, + 0x1.30d190130d190p-1, 0x1.2f684bda12f68p-1, 0x1.2e025c04b8097p-1, + 0x1.2c9fb4d812ca0p-1, 0x1.2b404ad012b40p-1, 0x1.29e4129e4129ep-1, + 0x1.288b01288b013p-1, 0x1.27350b8812735p-1, 0x1.25e22708092f1p-1, + 0x1.2492492492492p-1, 0x1.23456789abcdfp-1, 0x1.21fb78121fb78p-1, + 0x1.20b470c67c0d9p-1, 0x1.1f7047dc11f70p-1, 0x1.1e2ef3b3fb874p-1, + 0x1.1cf06ada2811dp-1, 0x1.1bb4a4046ed29p-1, 0x1.1a7b9611a7b96p-1, + 0x1.19453808ca29cp-1, 0x1.1811811811812p-1, 0x1.16e0689427379p-1, + 0x1.15b1e5f75270dp-1, 0x1.1485f0e0acd3bp-1, 0x1.135c81135c811p-1, + 0x1.12358e75d3033p-1, 0x1.1111111111111p-1, 0x1.0fef010fef011p-1, + 0x1.0ecf56be69c90p-1, 0x1.0db20a88f4696p-1, 0x1.0c9714fbcda3bp-1, + 0x1.0b7e6ec259dc8p-1, 0x1.0a6810a6810a7p-1, 0x1.0953f39010954p-1, + 0x1.0842108421084p-1, 0x1.073260a47f7c6p-1, 0x1.0624dd2f1a9fcp-1, + 0x1.05197f7d73404p-1, 0x1.0410410410410p-1, 0x1.03091b51f5e1ap-1, + 0x1.0204081020408p-1, 0x1.0101010101010p-1}; + +// Lookup table for log(f) = log(1 + n*2^(-7)) where n = 0..127. +static constexpr double LOG_F[128] = { + 0x0.0000000000000p+0, 0x1.fe02a6b106788p-8, 0x1.fc0a8b0fc03e3p-7, + 0x1.7b91b07d5b11ap-6, 0x1.f829b0e783300p-6, 0x1.39e87b9febd5fp-5, + 0x1.77458f632dcfcp-5, 0x1.b42dd711971bep-5, 0x1.f0a30c01162a6p-5, + 0x1.16536eea37ae0p-4, 0x1.341d7961bd1d0p-4, 0x1.51b073f06183fp-4, + 0x1.6f0d28ae56b4bp-4, 0x1.8c345d6319b20p-4, 0x1.a926d3a4ad563p-4, + 0x1.c5e548f5bc743p-4, 0x1.e27076e2af2e5p-4, 0x1.fec9131dbeabap-4, + 0x1.0d77e7cd08e59p-3, 0x1.1b72ad52f67a0p-3, 0x1.29552f81ff523p-3, + 0x1.371fc201e8f74p-3, 0x1.44d2b6ccb7d1ep-3, 0x1.526e5e3a1b437p-3, + 0x1.5ff3070a793d3p-3, 0x1.6d60fe719d21cp-3, 0x1.7ab890210d909p-3, + 0x1.87fa06520c910p-3, 0x1.9525a9cf456b4p-3, 0x1.a23bc1fe2b563p-3, + 0x1.af3c94e80bff2p-3, 0x1.bc286742d8cd6p-3, 0x1.c8ff7c79a9a21p-3, + 0x1.d5c216b4fbb91p-3, 0x1.e27076e2af2e5p-3, 0x1.ef0adcbdc5936p-3, + 0x1.fb9186d5e3e2ap-3, 0x1.0402594b4d040p-2, 0x1.0a324e27390e3p-2, + 0x1.1058bf9ae4ad5p-2, 0x1.1675cababa60ep-2, 0x1.1c898c16999fap-2, + 0x1.22941fbcf7965p-2, 0x1.2895a13de86a3p-2, 0x1.2e8e2bae11d30p-2, + 0x1.347dd9a987d54p-2, 0x1.3a64c556945e9p-2, 0x1.404308686a7e3p-2, + 0x1.4618bc21c5ec2p-2, 0x1.4be5f957778a0p-2, 0x1.51aad872df82dp-2, + 0x1.5767717455a6cp-2, 0x1.5d1bdbf5809cap-2, 0x1.62c82f2b9c795p-2, + 0x1.686c81e9b14aep-2, 0x1.6e08eaa2ba1e3p-2, 0x1.739d7f6bbd006p-2, + 0x1.792a55fdd47a2p-2, 0x1.7eaf83b82afc3p-2, 0x1.842d1da1e8b17p-2, + 0x1.89a3386c1425ap-2, 0x1.8f11e873662c7p-2, 0x1.947941c2116fap-2, + 0x1.99d958117e08ap-2, 0x1.9f323ecbf984bp-2, 0x1.a484090e5bb0ap-2, + 0x1.a9cec9a9a0849p-2, 0x1.af1293247786bp-2, 0x1.b44f77bcc8f62p-2, + 0x1.b9858969310fbp-2, 0x1.beb4d9da71b7bp-2, 0x1.c3dd7a7cdad4dp-2, + 0x1.c8ff7c79a9a21p-2, 0x1.ce1af0b85f3ebp-2, 0x1.d32fe7e00ebd5p-2, + 0x1.d83e7258a2f3ep-2, 0x1.dd46a04c1c4a0p-2, 0x1.e24881a7c6c26p-2, + 0x1.e744261d68787p-2, 0x1.ec399d2468cc0p-2, 0x1.f128f5faf06ecp-2, + 0x1.f6123fa7028acp-2, 0x1.faf588f78f31ep-2, 0x1.ffd2e0857f498p-2, + 0x1.02552a5a5d0fep-1, 0x1.04bdf9da926d2p-1, 0x1.0723e5c1cdf40p-1, + 0x1.0986f4f573520p-1, 0x1.0be72e4252a82p-1, 0x1.0e44985d1cc8bp-1, + 0x1.109f39e2d4c96p-1, 0x1.12f719593efbcp-1, 0x1.154c3d2f4d5e9p-1, + 0x1.179eabbd899a0p-1, 0x1.19ee6b467c96ep-1, 0x1.1c3b81f713c24p-1, + 0x1.1e85f5e7040d0p-1, 0x1.20cdcd192ab6dp-1, 0x1.23130d7bebf42p-1, + 0x1.2555bce98f7cbp-1, 0x1.2795e1289b11ap-1, 0x1.29d37fec2b08ap-1, + 0x1.2c0e9ed448e8bp-1, 0x1.2e47436e40268p-1, 0x1.307d7334f10bep-1, + 0x1.32b1339121d71p-1, 0x1.34e289d9ce1d3p-1, 0x1.37117b54747b5p-1, + 0x1.393e0d3562a19p-1, 0x1.3b68449fffc22p-1, 0x1.3d9026a7156fap-1, + 0x1.3fb5b84d16f42p-1, 0x1.41d8fe84672aep-1, 0x1.43f9fe2f9ce67p-1, + 0x1.4618bc21c5ec2p-1, 0x1.48353d1ea88dfp-1, 0x1.4a4f85db03ebbp-1, + 0x1.4c679afccee39p-1, 0x1.4e7d811b75bb0p-1, 0x1.50913cc01686bp-1, + 0x1.52a2d265bc5aap-1, 0x1.54b2467999497p-1, 0x1.56bf9d5b3f399p-1, + 0x1.58cadb5cd7989p-1, 0x1.5ad404c359f2cp-1, 0x1.5cdb1dc6c1764p-1, + 0x1.5ee02a9241675p-1, 0x1.60e32f44788d8p-1}; + +} // namespace acoshf_internal + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ACOSH_FLOAT_CONSTANTS_H diff --git a/libc/src/__support/math/acoshf.h b/libc/src/__support/math/acoshf.h new file mode 100644 index 0000000000000..f18f169f49bb8 --- /dev/null +++ b/libc/src/__support/math/acoshf.h @@ -0,0 +1,86 @@ +//===-- Implementation header for acoshf ------------------------*- 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_LIBC_SRC___SUPPORT_MATH_ACOSHF_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_ACOSHF_H + +#include "acoshf_utils.h" +#include "src/__support/FPUtil/FEnvImpl.h" +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/multiply_add.h" +#include "src/__support/FPUtil/sqrt.h" +#include "src/__support/macros/config.h" +#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY + +namespace LIBC_NAMESPACE_DECL { + +namespace math { + +static constexpr float acoshf(float x) { + using namespace acoshf_internal; + using FPBits_t = typename fputil::FPBits; + FPBits_t xbits(x); + + if (LIBC_UNLIKELY(x <= 1.0f)) { + if (x == 1.0f) + return 0.0f; + // x < 1. + fputil::set_errno_if_required(EDOM); + fputil::raise_except_if_required(FE_INVALID); + return FPBits_t::quiet_nan().get_val(); + } + +#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS + uint32_t x_u = xbits.uintval(); + if (LIBC_UNLIKELY(x_u >= 0x4f8ffb03)) { + if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) + return x; + + // Helper functions to set results for exceptional cases. + auto round_result_slightly_down = [](float r) -> float { + volatile float tmp = r; + tmp = tmp - 0x1.0p-25f; + return tmp; + }; + auto round_result_slightly_up = [](float r) -> float { + volatile float tmp = r; + tmp = tmp + 0x1.0p-25f; + return tmp; + }; + + switch (x_u) { + case 0x4f8ffb03: // x = 0x1.1ff606p32f + return round_result_slightly_up(0x1.6fdd34p4f); + case 0x5c569e88: // x = 0x1.ad3d1p57f + return round_result_slightly_up(0x1.45c146p5f); + case 0x5e68984e: // x = 0x1.d1309cp61f + return round_result_slightly_up(0x1.5c9442p5f); + case 0x655890d3: // x = 0x1.b121a6p75f + return round_result_slightly_down(0x1.a9a3f2p5f); + case 0x6eb1a8ec: // x = 0x1.6351d8p94f + return round_result_slightly_down(0x1.08b512p6f); + case 0x7997f30a: // x = 0x1.2fe614p116f + return round_result_slightly_up(0x1.451436p6f); + } + } +#else + if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) + return x; +#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS + + double x_d = static_cast(x); + // acosh(x) = log(x + sqrt(x^2 - 1)) + return static_cast(log_eval( + x_d + fputil::sqrt(fputil::multiply_add(x_d, x_d, -1.0)))); +} + +} // namespace math + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ACOSHF_H diff --git a/libc/src/__support/math/acoshf16.h b/libc/src/__support/math/acoshf16.h new file mode 100644 index 0000000000000..15e7f6ae7e208 --- /dev/null +++ b/libc/src/__support/math/acoshf16.h @@ -0,0 +1,123 @@ +//===-- Implementation header for acoshf16 ----------------------*- 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_LIBC_SRC___SUPPORT_MATH_ACOSHF_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_ACOSHF_H + +#include "include/llvm-libc-macros/float16-macros.h" + +#ifdef LIBC_TYPES_HAS_FLOAT16 + +#include "acoshf_utils.h" +#include "src/__support/FPUtil/FEnvImpl.h" +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/PolyEval.h" +#include "src/__support/FPUtil/cast.h" +#include "src/__support/FPUtil/except_value_utils.h" +#include "src/__support/FPUtil/multiply_add.h" +#include "src/__support/FPUtil/sqrt.h" +#include "src/__support/macros/config.h" +#include "src/__support/macros/optimization.h" + +namespace LIBC_NAMESPACE_DECL { + +namespace math { + +static constexpr float16 acoshf16(float16 x) { + + using namespace acoshf_internal; + constexpr size_t N_EXCEPTS = 2; + constexpr fputil::ExceptValues ACOSHF16_EXCEPTS{{ + // (input, RZ output, RU offset, RD offset, RN offset) + // x = 0x1.6dcp+1, acoshf16(x) = 0x1.b6p+0 (RZ) + {0x41B7, 0x3ED8, 1, 0, 0}, + // x = 0x1.39p+0, acoshf16(x) = 0x1.4f8p-1 (RZ) + {0x3CE4, 0x393E, 1, 0, 1}, + }}; + + using FPBits = fputil::FPBits; + FPBits xbits(x); + uint16_t x_u = xbits.uintval(); + + // Check for NaN input first. + if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) { + if (xbits.is_signaling_nan()) { + fputil::raise_except_if_required(FE_INVALID); + return FPBits::quiet_nan().get_val(); + } + if (xbits.is_neg()) { + fputil::set_errno_if_required(EDOM); + fputil::raise_except_if_required(FE_INVALID); + return FPBits::quiet_nan().get_val(); + } + return x; + } + + // Domain error for inputs less than 1.0. + if (LIBC_UNLIKELY(x <= 1.0f)) { + if (x == 1.0f) + return FPBits::zero().get_val(); + fputil::set_errno_if_required(EDOM); + fputil::raise_except_if_required(FE_INVALID); + return FPBits::quiet_nan().get_val(); + } + + if (auto r = ACOSHF16_EXCEPTS.lookup(xbits.uintval()); + LIBC_UNLIKELY(r.has_value())) + return r.value(); + + float xf = x; + // High-precision polynomial approximation for inputs close to 1.0 + // ([1, 1.25)). + // + // Brief derivation: + // 1. Expand acosh(1 + delta) using Taylor series around delta=0: + // acosh(1 + delta) ≈ sqrt(2 * delta) * [1 - delta/12 + 3*delta^2/160 + // - 5*delta^3/896 + 35*delta^4/18432 + ...] + // 2. Truncate the series to fit accurately for delta in [0, 0.25]. + // 3. Polynomial coefficients (from sollya) used here are: + // P(delta) ≈ 1 - 0x1.555556p-4 * delta + 0x1.333334p-6 * delta^2 + // - 0x1.6db6dcp-8 * delta^3 + 0x1.f1c71cp-10 * delta^4 + // 4. The Sollya commands used to generate these coefficients were: + // > display = hexadecimal; + // > round(1/12, SG, RN); + // > round(3/160, SG, RN); + // > round(5/896, SG, RN); + // > round(35/18432, SG, RN); + // With hexadecimal display mode enabled, the outputs were: + // 0x1.555556p-4 + // 0x1.333334p-6 + // 0x1.6db6dcp-8 + // 0x1.f1c71cp-10 + // 5. The maximum absolute error, estimated using: + // dirtyinfnorm(acosh(1 + x) - sqrt(2*x) * P(x), [0, 0.25]) + // is: + // 0x1.d84281p-22 + if (LIBC_UNLIKELY(x_u < 0x3D00U)) { + float delta = xf - 1.0f; + float sqrt_2_delta = fputil::sqrt(2.0 * delta); + float pe = fputil::polyeval(delta, 0x1p+0f, -0x1.555556p-4f, 0x1.333334p-6f, + -0x1.6db6dcp-8f, 0x1.f1c71cp-10f); + float approx = sqrt_2_delta * pe; + return fputil::cast(approx); + } + + // acosh(x) = log(x + sqrt(x^2 - 1)) + float sqrt_term = fputil::sqrt(fputil::multiply_add(xf, xf, -1.0f)); + float result = static_cast(log_eval(xf + sqrt_term)); + + return fputil::cast(result); +} + +} // namespace math + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LIBC_TYPES_HAS_FLOAT16 + +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ACOSHF_H diff --git a/libc/src/__support/math/acoshf_utils.h b/libc/src/__support/math/acoshf_utils.h new file mode 100644 index 0000000000000..808c3dd41cfe4 --- /dev/null +++ b/libc/src/__support/math/acoshf_utils.h @@ -0,0 +1,60 @@ +//===-- Collection of utils for acoshf --------------------------*- 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_LIBC_SRC___SUPPORT_MATH_ACOSHF_UTILS_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_ACOSHF_UTILS_H + +#include "acosh_float_constants.h" +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/PolyEval.h" +#include "src/__support/FPUtil/multiply_add.h" + +namespace LIBC_NAMESPACE_DECL { + +namespace acoshf_internal { + +// x should be positive, normal finite value +LIBC_INLINE static double log_eval(double x) { + // For x = 2^ex * (1 + mx) + // log(x) = ex * log(2) + log(1 + mx) + using FPB = fputil::FPBits; + FPB bs(x); + + double ex = static_cast(bs.get_exponent()); + + // p1 is the leading 7 bits of mx, i.e. + // p1 * 2^(-7) <= m_x < (p1 + 1) * 2^(-7). + int p1 = static_cast(bs.get_mantissa() >> (FPB::FRACTION_LEN - 7)); + + // Set bs to (1 + (mx - p1*2^(-7)) + bs.set_uintval(bs.uintval() & (FPB::FRACTION_MASK >> 7)); + bs.set_biased_exponent(FPB::EXP_BIAS); + // dx = (mx - p1*2^(-7)) / (1 + p1*2^(-7)). + double dx = (bs.get_val() - 1.0) * ONE_OVER_F[p1]; + + // Minimax polynomial of log(1 + dx) generated by Sollya with: + // > P = fpminimax(log(1 + x)/x, 6, [|D...|], [0, 2^-7]); + const double COEFFS[6] = {-0x1.ffffffffffffcp-2, 0x1.5555555552ddep-2, + -0x1.ffffffefe562dp-3, 0x1.9999817d3a50fp-3, + -0x1.554317b3f67a5p-3, 0x1.1dc5c45e09c18p-3}; + double dx2 = dx * dx; + double c1 = fputil::multiply_add(dx, COEFFS[1], COEFFS[0]); + double c2 = fputil::multiply_add(dx, COEFFS[3], COEFFS[2]); + double c3 = fputil::multiply_add(dx, COEFFS[5], COEFFS[4]); + + double p = fputil::polyeval(dx2, dx, c1, c2, c3); + double result = + fputil::multiply_add(ex, /*log(2)*/ 0x1.62e42fefa39efp-1, LOG_F[p1] + p); + return result; +} + +} // namespace acoshf_internal + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ACOSHF_UTILS_H diff --git a/libc/src/math/generic/asin_utils.h b/libc/src/__support/math/asin_utils.h similarity index 96% rename from libc/src/math/generic/asin_utils.h rename to libc/src/__support/math/asin_utils.h index 44913d573de2c..e0c9096e2bb78 100644 --- a/libc/src/math/generic/asin_utils.h +++ b/libc/src/__support/math/asin_utils.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_SRC_MATH_GENERIC_ASIN_UTILS_H -#define LLVM_LIBC_SRC_MATH_GENERIC_ASIN_UTILS_H +#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_ASIN_UTILS_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_ASIN_UTILS_H #include "src/__support/FPUtil/PolyEval.h" #include "src/__support/FPUtil/double_double.h" @@ -16,19 +16,18 @@ #include "src/__support/FPUtil/nearest_integer.h" #include "src/__support/integer_literals.h" #include "src/__support/macros/config.h" -#include "src/__support/macros/optimization.h" namespace LIBC_NAMESPACE_DECL { -namespace { +namespace asin_internal { using DoubleDouble = fputil::DoubleDouble; using Float128 = fputil::DyadicFloat<128>; -constexpr DoubleDouble PI = {0x1.1a62633145c07p-53, 0x1.921fb54442d18p1}; +static constexpr DoubleDouble PI = {0x1.1a62633145c07p-53, 0x1.921fb54442d18p1}; -constexpr DoubleDouble PI_OVER_TWO = {0x1.1a62633145c07p-54, - 0x1.921fb54442d18p0}; +static constexpr DoubleDouble PI_OVER_TWO = {0x1.1a62633145c07p-54, + 0x1.921fb54442d18p0}; #ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS @@ -39,14 +38,14 @@ constexpr DoubleDouble PI_OVER_TWO = {0x1.1a62633145c07p-54, // > dirtyinfnorm(asin(x)/x - P, [0, 0.5]); // 0x1.1a71ef0a0f26a9fb7ed7e41dee788b13d1770db3dp-52 -constexpr double ASIN_COEFFS[12] = { +static constexpr double ASIN_COEFFS[12] = { 0x1.0000000000000p0, 0x1.5555555556dcfp-3, 0x1.3333333082e11p-4, 0x1.6db6dd14099edp-5, 0x1.f1c69b35bf81fp-6, 0x1.6e97194225a67p-6, 0x1.1babddb82ce12p-6, 0x1.d55bd078600d6p-7, 0x1.33328959e63d6p-7, 0x1.2b5993bda1d9bp-6, -0x1.806aff270bf25p-7, 0x1.02614e5ed3936p-5, }; -LIBC_INLINE double asin_eval(double u) { +LIBC_INLINE static constexpr double asin_eval(double u) { double u2 = u * u; double c0 = fputil::multiply_add(u, ASIN_COEFFS[1], ASIN_COEFFS[0]); double c1 = fputil::multiply_add(u, ASIN_COEFFS[3], ASIN_COEFFS[2]); @@ -124,7 +123,7 @@ LIBC_INLINE double asin_eval(double u) { // > dirtyinfnorm(asin(x)/x - P, [-1/64, 1/64]); // 0x1.999075402cafp-83 -constexpr double ASIN_COEFFS[9][12] = { +static constexpr double ASIN_COEFFS[9][12] = { {1.0, 0.0, 0x1.5555555555555p-3, 0x1.5555555555555p-57, 0x1.3333333333333p-4, 0x1.6db6db6db6db7p-5, 0x1.f1c71c71c71c7p-6, 0x1.6e8ba2e8ba2e9p-6, 0x1.1c4ec4ec4ec4fp-6, 0x1.c99999999999ap-7, @@ -164,8 +163,8 @@ constexpr double ASIN_COEFFS[9][12] = { }; // We calculate the lower part of the approximation P(u). -LIBC_INLINE DoubleDouble asin_eval(const DoubleDouble &u, unsigned &idx, - double &err) { +LIBC_INLINE static DoubleDouble asin_eval(const DoubleDouble &u, unsigned &idx, + double &err) { using fputil::multiply_add; // k = round(u * 32). double k = fputil::nearest_integer(u.hi * 0x1.0p5); @@ -239,7 +238,7 @@ LIBC_INLINE DoubleDouble asin_eval(const DoubleDouble &u, unsigned &idx, // + (676039 x^24)/104857600 + (1300075 x^26)/226492416 + // + (5014575 x^28)/973078528 + (9694845 x^30)/2080374784. -constexpr Float128 ASIN_COEFFS_F128[17][16] = { +static constexpr Float128 ASIN_COEFFS_F128[17][16] = { { {Sign::POS, -127, 0x80000000'00000000'00000000'00000000_u128}, {Sign::POS, -130, 0xaaaaaaaa'aaaaaaaa'aaaaaaaa'aaaaaaab_u128}, @@ -548,13 +547,14 @@ constexpr Float128 ASIN_COEFFS_F128[17][16] = { }, }; -constexpr Float128 PI_OVER_TWO_F128 = { +static constexpr Float128 PI_OVER_TWO_F128 = { Sign::POS, -127, 0xc90fdaa2'2168c234'c4c6628b'80dc1cd1_u128}; -constexpr Float128 PI_F128 = {Sign::POS, -126, - 0xc90fdaa2'2168c234'c4c6628b'80dc1cd1_u128}; +static constexpr Float128 PI_F128 = { + Sign::POS, -126, 0xc90fdaa2'2168c234'c4c6628b'80dc1cd1_u128}; -LIBC_INLINE Float128 asin_eval(const Float128 &u, unsigned idx) { +LIBC_INLINE static constexpr Float128 asin_eval(const Float128 &u, + unsigned idx) { return fputil::polyeval(u, ASIN_COEFFS_F128[idx][0], ASIN_COEFFS_F128[idx][1], ASIN_COEFFS_F128[idx][2], ASIN_COEFFS_F128[idx][3], ASIN_COEFFS_F128[idx][4], ASIN_COEFFS_F128[idx][5], @@ -567,8 +567,8 @@ LIBC_INLINE Float128 asin_eval(const Float128 &u, unsigned idx) { #endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS -} // anonymous namespace +} // namespace asin_internal } // namespace LIBC_NAMESPACE_DECL -#endif // LLVM_LIBC_SRC_MATH_GENERIC_ASIN_UTILS_H +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ASIN_UTILS_H diff --git a/libc/src/__support/math/erff.h b/libc/src/__support/math/erff.h new file mode 100644 index 0000000000000..e54ec77b9def7 --- /dev/null +++ b/libc/src/__support/math/erff.h @@ -0,0 +1,193 @@ +//===-- Implementation header for erff --------------------------*- 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_LIBC_SRC___SUPPORT_MATH_ERFF_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_ERFF_H + +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/except_value_utils.h" +#include "src/__support/FPUtil/multiply_add.h" +#include "src/__support/macros/config.h" +#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY + +namespace LIBC_NAMESPACE_DECL { + +namespace math { + +static constexpr float erff(float x) { + + // Polynomials approximating erf(x)/x on ( k/8, (k + 1)/8 ) generated by + // Sollya with: > P = fpminimax(erf(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14|], + // [|D...|], + // [k/8, (k + 1)/8]); + // for k = 0..31. + constexpr double COEFFS[32][8] = { + {0x1.20dd750429b6dp0, -0x1.812746b037753p-2, 0x1.ce2f219e8596ap-4, + -0x1.b82cdacb78fdap-6, 0x1.56479297dfda5p-8, -0x1.8b3ac5455ef02p-11, + -0x1.126fcac367e3bp-8, 0x1.2d0bdb3ba4984p-4}, + {0x1.20dd750429b6dp0, -0x1.812746b0379a8p-2, 0x1.ce2f21a03cf2ap-4, + -0x1.b82ce30de083ep-6, 0x1.565bcad3eb60fp-8, -0x1.c02c66f659256p-11, + 0x1.f92f673385229p-14, -0x1.def402648ae9p-17}, + {0x1.20dd750429b34p0, -0x1.812746b032dcep-2, 0x1.ce2f219d84aaep-4, + -0x1.b82ce22dcf139p-6, 0x1.565b9efcd4af1p-8, -0x1.c021f1af414bcp-11, + 0x1.f7c6d177eff82p-14, -0x1.c9e4410dcf865p-17}, + {0x1.20dd750426eabp0, -0x1.812746ae592c7p-2, 0x1.ce2f211525f14p-4, + -0x1.b82ccc125e63fp-6, 0x1.56596f261cfd3p-8, -0x1.bfde1ff8eeecfp-11, + 0x1.f31a9d15dc5d8p-14, -0x1.a5a4362844b3cp-17}, + {0x1.20dd75039c705p0, -0x1.812746777e74dp-2, 0x1.ce2f17af98a1bp-4, + -0x1.b82be4b817cbep-6, 0x1.564bec2e2962ep-8, -0x1.bee86f9da3558p-11, + 0x1.e9443689dc0ccp-14, -0x1.79c0f230805d8p-17}, + {0x1.20dd74f811211p0, -0x1.81274371a3e8fp-2, 0x1.ce2ec038262e5p-4, + -0x1.b8265b82c5e1fp-6, 0x1.5615a2e239267p-8, -0x1.bc63ae023dcebp-11, + 0x1.d87c2102f7e06p-14, -0x1.49584bea41d62p-17}, + {0x1.20dd746d063e3p0, -0x1.812729a8a950fp-2, 0x1.ce2cb0a2df232p-4, + -0x1.b80eca1f51278p-6, 0x1.5572e26c46815p-8, -0x1.b715e5638b65ep-11, + 0x1.bfbb195484968p-14, -0x1.177a565c15c52p-17}, + {0x1.20dd701b44486p0, -0x1.812691145f237p-2, 0x1.ce23a06b8cfd9p-4, + -0x1.b7c1dc7245288p-6, 0x1.53e92f7f397ddp-8, -0x1.ad97cc4acf0b2p-11, + 0x1.9f028b2b09b71p-14, -0x1.cdc4da08da8c1p-18}, + {0x1.20dd5715ac332p0, -0x1.8123e680bd0ebp-2, 0x1.ce0457aded691p-4, + -0x1.b6f52d52bed4p-6, 0x1.50c291b84414cp-8, -0x1.9ea246b1ad4a9p-11, + 0x1.77654674e0cap-14, -0x1.737c11a1bcebbp-18}, + {0x1.20dce6593e114p0, -0x1.811a59c02eadcp-2, 0x1.cdab53c7cd7d5p-4, + -0x1.b526d2e321eedp-6, 0x1.4b1d32cd8b994p-8, -0x1.8963143ec0a1ep-11, + 0x1.4ad5700e4db91p-14, -0x1.231e100e43ef2p-18}, + {0x1.20db48bfd5a62p0, -0x1.80fdd84f9e308p-2, 0x1.ccd340d462983p-4, + -0x1.b196a2928768p-6, 0x1.4210c2c13a0f7p-8, -0x1.6dbdfb4ff71aep-11, + 0x1.1bca2d17fbd71p-14, -0x1.bca36f90c7cf5p-19}, + {0x1.20d64b2f8f508p0, -0x1.80b4d4f19fa8bp-2, 0x1.cb088197262e3p-4, + -0x1.ab51fd02e5b99p-6, 0x1.34e1e5e81a632p-8, -0x1.4c66377b502cep-11, + 0x1.d9ad25066213cp-15, -0x1.4b0df7dd0cfa1p-19}, + {0x1.20c8fc1243576p0, -0x1.8010cb2009e27p-2, 0x1.c7a47e9299315p-4, + -0x1.a155be5683654p-6, 0x1.233502694997bp-8, -0x1.26c94b7d813p-11, + 0x1.8094f1de25fb9p-15, -0x1.e0e3d776c6eefp-20}, + {0x1.20a9bd1611bc1p0, -0x1.7ec7fbce83f9p-2, 0x1.c1d757d7317b7p-4, + -0x1.92c160cd589fp-6, 0x1.0d307269cc5c2p-8, -0x1.fda5b0d2d1879p-12, + 0x1.2fdd7b3b14a7fp-15, -0x1.54eed4a26af5ap-20}, + {0x1.20682834f943dp0, -0x1.7c73f747bf5a9p-2, 0x1.b8c2db4a9ffd1p-4, + -0x1.7f0e4ffe989ecp-6, 0x1.e7061eae4166ep-9, -0x1.ad36e873fff2dp-12, + 0x1.d39222396128ep-16, -0x1.d83dacec5ea6bp-21}, + {0x1.1feb8d12676d7p0, -0x1.7898347284afep-2, 0x1.aba3466b34451p-4, + -0x1.663adc573e2f9p-6, 0x1.ae99fb17c3e08p-9, -0x1.602f950ad5535p-12, + 0x1.5e9717490609dp-16, -0x1.3fca107bbc8d5p-21}, + {0x1.1f12fe3c536fap0, -0x1.72b1d1f22e6d3p-2, 0x1.99fc0eed4a896p-4, + -0x1.48db0a87bd8c6p-6, 0x1.73e368895aa61p-9, -0x1.19b35d5301fc8p-12, + 0x1.007987e4bb033p-16, -0x1.a7edcd4c2dc7p-22}, + {0x1.1db7b0df84d5dp0, -0x1.6a4e4a41cde02p-2, 0x1.83bbded16455dp-4, + -0x1.2809b3b36977ep-6, 0x1.39c08bab44679p-9, -0x1.b7b45a70ed119p-13, + 0x1.6e99b36410e7bp-17, -0x1.13619bb7ebc0cp-22}, + {0x1.1bb1c85c4a527p0, -0x1.5f23b99a249a3p-2, 0x1.694c91fa0d12cp-4, + -0x1.053e1ce11c72dp-6, 0x1.02bf72c50ea78p-9, -0x1.4f478fb56cb02p-13, + 0x1.005f80ecbe213p-17, -0x1.5f2446bde7f5bp-23}, + {0x1.18dec3bd51f9dp0, -0x1.5123f58346186p-2, 0x1.4b8a1ca536ab4p-4, + -0x1.c4243015cc723p-7, 0x1.a1a8a01d351efp-10, -0x1.f466b34f1d86bp-14, + 0x1.5f835eea0bf6ap-18, -0x1.b83165b939234p-24}, + {0x1.152804c3369f4p0, -0x1.4084cd4afd4bcp-2, 0x1.2ba2e836e47aap-4, + -0x1.800f2dfc6904bp-7, 0x1.4a6daf0669c59p-10, -0x1.6e326ab872317p-14, + 0x1.d9761a6a755a5p-19, -0x1.0fca33f9dd4b5p-24}, + {0x1.1087ad68356aap0, -0x1.2dbb044707459p-2, 0x1.0aea8ceaa0384p-4, + -0x1.40b516d52b3d2p-7, 0x1.00c9e05f01d22p-10, -0x1.076afb0dc0ff7p-14, + 0x1.39fadec400657p-19, -0x1.4b5761352e7e3p-25}, + {0x1.0b0a7a8ba4a22p0, -0x1.196990d22d4a1p-2, 0x1.d5551e6ac0c4dp-5, + -0x1.07cce1770bd1ap-7, 0x1.890347b8848bfp-11, -0x1.757ec96750b6ap-15, + 0x1.9b258a1e06bcep-20, -0x1.8fc6d22da7572p-26}, + {0x1.04ce2be70fb47p0, -0x1.0449e4b0b9cacp-2, 0x1.97f7424f4b0e7p-5, + -0x1.ac825439c42f4p-8, 0x1.28f5f65426dfbp-11, -0x1.05b699a90f90fp-15, + 0x1.0a888eecf4593p-20, -0x1.deace2b32bb31p-27}, + {0x1.fbf9fb0e11cc8p-1, -0x1.de2640856545ap-3, 0x1.5f5b1f47f851p-5, + -0x1.588bc71eb41b9p-8, 0x1.bc6a0a772f56dp-12, -0x1.6b9fad1f1657ap-16, + 0x1.573204ba66504p-21, -0x1.1d38065c94e44p-27}, + {0x1.ed8f18c99e031p-1, -0x1.b4cb6acd903b4p-3, 0x1.2c7f3dddd6fc1p-5, + -0x1.13052067df4ep-8, 0x1.4a5027444082fp-12, -0x1.f672bab0e2554p-17, + 0x1.b83c756348cc9p-22, -0x1.534f1a1079499p-28}, + {0x1.debd33044166dp-1, -0x1.8d7cd9053f7d8p-3, 0x1.ff9957fb3d6e7p-6, + -0x1.b50be55de0f36p-9, 0x1.e92c8ec53a628p-13, -0x1.5a4b88d508007p-17, + 0x1.1a27737559e26p-22, -0x1.942ae62cb2c14p-29}, + {0x1.cfdbf0386f3bdp-1, -0x1.68e33d93b0dc4p-3, 0x1.b2683d58f53dep-6, + -0x1.5a9174e70d26fp-9, 0x1.69ddd326d49cdp-13, -0x1.dd8f397a8219cp-18, + 0x1.6a755016ad4ddp-23, -0x1.e366e0139187dp-30}, + {0x1.c132adb8d7464p-1, -0x1.475a899f61b46p-3, 0x1.70a431397a77cp-6, + -0x1.12e3d35beeee2p-9, 0x1.0c16b05738333p-13, -0x1.4a47f873e144ep-18, + 0x1.d3d494c698c02p-24, -0x1.2302c59547fe5p-30}, + {0x1.b2f5fd05555e7p-1, -0x1.28feefbe03ec7p-3, 0x1.3923acbb3a676p-6, + -0x1.b4ff793cd6358p-10, 0x1.8ea0eb8c913bcp-14, -0x1.cb31ec2baceb1p-19, + 0x1.30011e7e80c04p-24, -0x1.617710635cb1dp-31}, + {0x1.a54853cd9593ep-1, -0x1.0dbdbaea4dc8ep-3, 0x1.0a93e2c20a0fdp-6, + -0x1.5c969ff401ea8p-10, 0x1.29e0cc64fe627p-14, -0x1.4160d8e9d3c2ap-19, + 0x1.8e7b67594624ap-25, -0x1.b1cf2c975b09bp-32}, + {0x1.983ceece09ff8p-1, -0x1.eacc78f7a2dp-4, 0x1.c74418410655fp-7, + -0x1.1756a050e441ep-10, 0x1.bff3650f7f548p-15, -0x1.c56c0217d3adap-20, + 0x1.07b4918d0b489p-25, -0x1.0d4be8c1c50f8p-32}, + }; + + using FPBits = typename fputil::FPBits; + FPBits xbits(x); + + uint32_t x_u = xbits.uintval(); + uint32_t x_abs = x_u & 0x7fff'ffffU; + + if (LIBC_UNLIKELY(x_abs >= 0x4080'0000U)) { + constexpr float ONE[2] = {1.0f, -1.0f}; + constexpr float SMALL[2] = {-0x1.0p-25f, 0x1.0p-25f}; + + int sign = xbits.is_neg() ? 1 : 0; + + if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) { + if (xbits.is_signaling_nan()) { + fputil::raise_except_if_required(FE_INVALID); + return FPBits::quiet_nan().get_val(); + } + return (x_abs > 0x7f80'0000) ? x : ONE[sign]; + } + + return ONE[sign] + SMALL[sign]; + } + +#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS + // Exceptional mask = common 0 bits of 2 exceptional values. + constexpr uint32_t EXCEPT_MASK = 0x809a'6184U; + + if (LIBC_UNLIKELY((x_abs & EXCEPT_MASK) == 0)) { + // Exceptional values + if (LIBC_UNLIKELY(x_abs == 0x3f65'9229U)) // |x| = 0x1.cb2452p-1f + return x < 0.0f ? fputil::round_result_slightly_down(-0x1.972ea8p-1f) + : fputil::round_result_slightly_up(0x1.972ea8p-1f); + if (LIBC_UNLIKELY(x_abs == 0x4004'1e6aU)) // |x| = 0x1.083cd4p+1f + return x < 0.0f ? fputil::round_result_slightly_down(-0x1.fe3462p-1f) + : fputil::round_result_slightly_up(0x1.fe3462p-1f); + if (x_abs == 0U) + return x; + } +#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS + + // Polynomial approximation: + // erf(x) ~ x * (c0 + c1 * x^2 + c2 * x^4 + ... + c7 * x^14) + double xd = static_cast(x); + double xsq = xd * xd; + + constexpr uint32_t EIGHT = 3 << FPBits::FRACTION_LEN; + int idx = static_cast(FPBits(x_abs + EIGHT).get_val()); + + double x4 = xsq * xsq; + double c0 = fputil::multiply_add(xsq, COEFFS[idx][1], COEFFS[idx][0]); + double c1 = fputil::multiply_add(xsq, COEFFS[idx][3], COEFFS[idx][2]); + double c2 = fputil::multiply_add(xsq, COEFFS[idx][5], COEFFS[idx][4]); + double c3 = fputil::multiply_add(xsq, COEFFS[idx][7], COEFFS[idx][6]); + + double x8 = x4 * x4; + double p0 = fputil::multiply_add(x4, c1, c0); + double p1 = fputil::multiply_add(x4, c3, c2); + + return static_cast(xd * fputil::multiply_add(x8, p1, p0)); +} + +} // namespace math + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ERFF_H diff --git a/libc/src/__support/math/exp.h b/libc/src/__support/math/exp.h index a538df1e825dc..ff59ff79e3381 100644 --- a/libc/src/__support/math/exp.h +++ b/libc/src/__support/math/exp.h @@ -40,11 +40,11 @@ static constexpr double LOG2_E = 0x1.71547652b82fep+0; // Error bounds: // Errors when using double precision. -static constexpr double ERR_D = 0x1.8p-63; +static constexpr double EXP_ERR_D = 0x1.8p-63; #ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS // Errors when using double-double precision. -static constexpr double ERR_DD = 0x1.0p-99; +static constexpr double EXP_ERR_DD = 0x1.0p-99; #endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS // -2^-12 * log(2) @@ -387,7 +387,8 @@ static double exp(double x) { #ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS if (LIBC_UNLIKELY(denorm)) { - return ziv_test_denorm(hi, exp_mid.hi, lo, ERR_D) + return ziv_test_denorm(hi, exp_mid.hi, lo, + EXP_ERR_D) .value(); } else { // to multiply by 2^hi, a fast way is to simply add hi to the exponent @@ -399,12 +400,12 @@ static double exp(double x) { } #else if (LIBC_UNLIKELY(denorm)) { - if (auto r = ziv_test_denorm(hi, exp_mid.hi, lo, ERR_D); + if (auto r = ziv_test_denorm(hi, exp_mid.hi, lo, EXP_ERR_D); LIBC_LIKELY(r.has_value())) return r.value(); } else { - double upper = exp_mid.hi + (lo + ERR_D); - double lower = exp_mid.hi + (lo - ERR_D); + double upper = exp_mid.hi + (lo + EXP_ERR_D); + double lower = exp_mid.hi + (lo - EXP_ERR_D); if (LIBC_LIKELY(upper == lower)) { // to multiply by 2^hi, a fast way is to simply add hi to the exponent @@ -419,12 +420,12 @@ static double exp(double x) { DoubleDouble r_dd = exp_double_double(x, kd, exp_mid); if (LIBC_UNLIKELY(denorm)) { - if (auto r = ziv_test_denorm(hi, r_dd.hi, r_dd.lo, ERR_DD); + if (auto r = ziv_test_denorm(hi, r_dd.hi, r_dd.lo, EXP_ERR_DD); LIBC_LIKELY(r.has_value())) return r.value(); } else { - double upper_dd = r_dd.hi + (r_dd.lo + ERR_DD); - double lower_dd = r_dd.hi + (r_dd.lo - ERR_DD); + double upper_dd = r_dd.hi + (r_dd.lo + EXP_ERR_DD); + double lower_dd = r_dd.hi + (r_dd.lo - EXP_ERR_DD); if (LIBC_LIKELY(upper_dd == lower_dd)) { int64_t exp_hi = static_cast(hi) << FPBits::FRACTION_LEN; diff --git a/libc/src/__support/math/exp10.h b/libc/src/__support/math/exp10.h new file mode 100644 index 0000000000000..fa60e40c43e5d --- /dev/null +++ b/libc/src/__support/math/exp10.h @@ -0,0 +1,502 @@ +//===-- Implementation header for exp10 ------------------------*- 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_LIBC_SRC___SUPPORT_MATH_EXP10_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_EXP10_H + +#include "exp_constants.h" // Lookup tables EXP2_MID1 and EXP_M2. +#include "exp_utils.h" // ziv_test_denorm. +#include "src/__support/CPP/bit.h" +#include "src/__support/CPP/optional.h" +#include "src/__support/FPUtil/FEnvImpl.h" +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/PolyEval.h" +#include "src/__support/FPUtil/double_double.h" +#include "src/__support/FPUtil/dyadic_float.h" +#include "src/__support/FPUtil/multiply_add.h" +#include "src/__support/FPUtil/nearest_integer.h" +#include "src/__support/FPUtil/rounding_mode.h" +#include "src/__support/FPUtil/triple_double.h" +#include "src/__support/common.h" +#include "src/__support/integer_literals.h" +#include "src/__support/macros/config.h" +#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY + +namespace LIBC_NAMESPACE_DECL { + +using fputil::DoubleDouble; +using fputil::TripleDouble; +using Float128 = typename fputil::DyadicFloat<128>; + +using LIBC_NAMESPACE::operator""_u128; + +// log2(10) +static constexpr double LOG2_10 = 0x1.a934f0979a371p+1; + +// -2^-12 * log10(2) +// > a = -2^-12 * log10(2); +// > b = round(a, 32, RN); +// > c = round(a - b, 32, RN); +// > d = round(a - b - c, D, RN); +// Errors < 1.5 * 2^-144 +static constexpr double MLOG10_2_EXP2_M12_HI = -0x1.3441350ap-14; +static constexpr double MLOG10_2_EXP2_M12_MID = 0x1.0c0219dc1da99p-51; + +#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS +static constexpr double MLOG10_2_EXP2_M12_MID_32 = 0x1.0c0219dcp-51; +static constexpr double MLOG10_2_EXP2_M12_LO = 0x1.da994fd20dba2p-87; +#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS + +// Error bounds: +// Errors when using double precision. +constexpr double EXP10_ERR_D = 0x1.8p-63; + +#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS +// Errors when using double-double precision. +static constexpr double EXP10_ERR_DD = 0x1.8p-99; +#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS + +// Polynomial approximations with double precision. Generated by Sollya with: +// > P = fpminimax((10^x - 1)/x, 3, [|D...|], [-2^-14, 2^-14]); +// > P; +// Error bounds: +// | output - (10^dx - 1) / dx | < 2^-52. +LIBC_INLINE static double exp10_poly_approx_d(double dx) { + // dx^2 + double dx2 = dx * dx; + double c0 = + fputil::multiply_add(dx, 0x1.53524c73cea6ap+1, 0x1.26bb1bbb55516p+1); + double c1 = + fputil::multiply_add(dx, 0x1.2bd75cc6afc65p+0, 0x1.0470587aa264cp+1); + double p = fputil::multiply_add(dx2, c1, c0); + return p; +} + +#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS +// Polynomial approximation with double-double precision. Generated by Solya +// with: +// > P = fpminimax((10^x - 1)/x, 5, [|DD...|], [-2^-14, 2^-14]); +// Error bounds: +// | output - 10^(dx) | < 2^-101 +static constexpr DoubleDouble exp10_poly_approx_dd(const DoubleDouble &dx) { + // Taylor polynomial. + constexpr DoubleDouble COEFFS[] = { + {0, 0x1p0}, + {-0x1.f48ad494e927bp-53, 0x1.26bb1bbb55516p1}, + {-0x1.e2bfab3191cd2p-53, 0x1.53524c73cea69p1}, + {0x1.80fb65ec3b503p-53, 0x1.0470591de2ca4p1}, + {0x1.338fc05e21e55p-54, 0x1.2bd7609fd98c4p0}, + {0x1.d4ea116818fbp-56, 0x1.1429ffd519865p-1}, + {-0x1.872a8ff352077p-57, 0x1.a7ed70847c8b3p-3}, + + }; + + DoubleDouble p = fputil::polyeval(dx, COEFFS[0], COEFFS[1], COEFFS[2], + COEFFS[3], COEFFS[4], COEFFS[5], COEFFS[6]); + return p; +} + +// Polynomial approximation with 128-bit precision: +// Return exp(dx) ~ 1 + a0 * dx + a1 * dx^2 + ... + a6 * dx^7 +// For |dx| < 2^-14: +// | output - 10^dx | < 1.5 * 2^-124. +static constexpr Float128 exp10_poly_approx_f128(const Float128 &dx) { + constexpr Float128 COEFFS_128[]{ + {Sign::POS, -127, 0x80000000'00000000'00000000'00000000_u128}, // 1.0 + {Sign::POS, -126, 0x935d8ddd'aaa8ac16'ea56d62b'82d30a2d_u128}, + {Sign::POS, -126, 0xa9a92639'e753443a'80a99ce7'5f4d5bdb_u128}, + {Sign::POS, -126, 0x82382c8e'f1652304'6a4f9d7d'bf6c9635_u128}, + {Sign::POS, -124, 0x12bd7609'fd98c44c'34578701'9216c7af_u128}, + {Sign::POS, -127, 0x450a7ff4'7535d889'cc41ed7e'0d27aee5_u128}, + {Sign::POS, -130, 0xd3f6b844'702d636b'8326bb91'a6e7601d_u128}, + {Sign::POS, -130, 0x45b937f0'd05bb1cd'fa7b46df'314112a9_u128}, + }; + + Float128 p = fputil::polyeval(dx, COEFFS_128[0], COEFFS_128[1], COEFFS_128[2], + COEFFS_128[3], COEFFS_128[4], COEFFS_128[5], + COEFFS_128[6], COEFFS_128[7]); + return p; +} + +// Compute 10^(x) using 128-bit precision. +// TODO(lntue): investigate triple-double precision implementation for this +// step. +static Float128 exp10_f128(double x, double kd, int idx1, int idx2) { + double t1 = fputil::multiply_add(kd, MLOG10_2_EXP2_M12_HI, x); // exact + double t2 = kd * MLOG10_2_EXP2_M12_MID_32; // exact + double t3 = kd * MLOG10_2_EXP2_M12_LO; // Error < 2^-144 + + Float128 dx = fputil::quick_add( + Float128(t1), fputil::quick_add(Float128(t2), Float128(t3))); + + // TODO: Skip recalculating exp_mid1 and exp_mid2. + Float128 exp_mid1 = + fputil::quick_add(Float128(EXP2_MID1[idx1].hi), + fputil::quick_add(Float128(EXP2_MID1[idx1].mid), + Float128(EXP2_MID1[idx1].lo))); + + Float128 exp_mid2 = + fputil::quick_add(Float128(EXP2_MID2[idx2].hi), + fputil::quick_add(Float128(EXP2_MID2[idx2].mid), + Float128(EXP2_MID2[idx2].lo))); + + Float128 exp_mid = fputil::quick_mul(exp_mid1, exp_mid2); + + Float128 p = exp10_poly_approx_f128(dx); + + Float128 r = fputil::quick_mul(exp_mid, p); + + r.exponent += static_cast(kd) >> 12; + + return r; +} + +// Compute 10^x with double-double precision. +static DoubleDouble exp10_double_double(double x, double kd, + const DoubleDouble &exp_mid) { + // Recalculate dx: + // dx = x - k * 2^-12 * log10(2) + double t1 = fputil::multiply_add(kd, MLOG10_2_EXP2_M12_HI, x); // exact + double t2 = kd * MLOG10_2_EXP2_M12_MID_32; // exact + double t3 = kd * MLOG10_2_EXP2_M12_LO; // Error < 2^-140 + + DoubleDouble dx = fputil::exact_add(t1, t2); + dx.lo += t3; + + // Degree-6 polynomial approximation in double-double precision. + // | p - 10^x | < 2^-103. + DoubleDouble p = exp10_poly_approx_dd(dx); + + // Error bounds: 2^-102. + DoubleDouble r = fputil::quick_mult(exp_mid, p); + + return r; +} +#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS + +// When output is denormal. +static double exp10_denorm(double x) { + // Range reduction. + double tmp = fputil::multiply_add(x, LOG2_10, 0x1.8000'0000'4p21); + int k = static_cast(cpp::bit_cast(tmp) >> 19); + double kd = static_cast(k); + + uint32_t idx1 = (k >> 6) & 0x3f; + uint32_t idx2 = k & 0x3f; + + int hi = k >> 12; + + DoubleDouble exp_mid1{EXP2_MID1[idx1].mid, EXP2_MID1[idx1].hi}; + DoubleDouble exp_mid2{EXP2_MID2[idx2].mid, EXP2_MID2[idx2].hi}; + DoubleDouble exp_mid = fputil::quick_mult(exp_mid1, exp_mid2); + + // |dx| < 1.5 * 2^-15 + 2^-31 < 2^-14 + double lo_h = fputil::multiply_add(kd, MLOG10_2_EXP2_M12_HI, x); // exact + double dx = fputil::multiply_add(kd, MLOG10_2_EXP2_M12_MID, lo_h); + + double mid_lo = dx * exp_mid.hi; + + // Approximate (10^dx - 1)/dx ~ 1 + a0*dx + a1*dx^2 + a2*dx^3 + a3*dx^4. + double p = exp10_poly_approx_d(dx); + + double lo = fputil::multiply_add(p, mid_lo, exp_mid.lo); + +#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS + return ziv_test_denorm(hi, exp_mid.hi, lo, + EXP10_ERR_D) + .value(); +#else + if (auto r = ziv_test_denorm(hi, exp_mid.hi, lo, EXP10_ERR_D); + LIBC_LIKELY(r.has_value())) + return r.value(); + + // Use double-double + DoubleDouble r_dd = exp10_double_double(x, kd, exp_mid); + + if (auto r = ziv_test_denorm(hi, r_dd.hi, r_dd.lo, EXP10_ERR_DD); + LIBC_LIKELY(r.has_value())) + return r.value(); + + // Use 128-bit precision + Float128 r_f128 = exp10_f128(x, kd, idx1, idx2); + + return static_cast(r_f128); +#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS +} + +// Check for exceptional cases when: +// * log10(1 - 2^-54) < x < log10(1 + 2^-53) +// * x >= log10(2^1024) +// * x <= log10(2^-1022) +// * x is inf or nan +static constexpr double exp10_set_exceptional(double x) { + using FPBits = typename fputil::FPBits; + FPBits xbits(x); + + uint64_t x_u = xbits.uintval(); + uint64_t x_abs = xbits.abs().uintval(); + + // |x| < log10(1 + 2^-53) + if (x_abs <= 0x3c8bcb7b1526e50e) { + // 10^(x) ~ 1 + x/2 + return fputil::multiply_add(x, 0.5, 1.0); + } + + // x <= log10(2^-1022) || x >= log10(2^1024) or inf/nan. + if (x_u >= 0xc0733a7146f72a42) { + // x <= log10(2^-1075) or -inf/nan + if (x_u > 0xc07439b746e36b52) { + // exp(-Inf) = 0 + if (xbits.is_inf()) + return 0.0; + + // exp(nan) = nan + if (xbits.is_nan()) + return x; + + if (fputil::quick_get_round() == FE_UPWARD) + return FPBits::min_subnormal().get_val(); + fputil::set_errno_if_required(ERANGE); + fputil::raise_except_if_required(FE_UNDERFLOW); + return 0.0; + } + + return exp10_denorm(x); + } + + // x >= log10(2^1024) or +inf/nan + // x is finite + if (x_u < 0x7ff0'0000'0000'0000ULL) { + int rounding = fputil::quick_get_round(); + if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO) + return FPBits::max_normal().get_val(); + + fputil::set_errno_if_required(ERANGE); + fputil::raise_except_if_required(FE_OVERFLOW); + } + // x is +inf or nan + return x + FPBits::inf().get_val(); +} + +namespace math { + +static constexpr double exp10(double x) { + using FPBits = typename fputil::FPBits; + FPBits xbits(x); + + uint64_t x_u = xbits.uintval(); + + // x <= log10(2^-1022) or x >= log10(2^1024) or + // log10(1 - 2^-54) < x < log10(1 + 2^-53). + if (LIBC_UNLIKELY(x_u >= 0xc0733a7146f72a42 || + (x_u <= 0xbc7bcb7b1526e50e && x_u >= 0x40734413509f79ff) || + x_u < 0x3c8bcb7b1526e50e)) { + return exp10_set_exceptional(x); + } + + // Now log10(2^-1075) < x <= log10(1 - 2^-54) or + // log10(1 + 2^-53) < x < log10(2^1024) + + // Range reduction: + // Let x = log10(2) * (hi + mid1 + mid2) + lo + // in which: + // hi is an integer + // mid1 * 2^6 is an integer + // mid2 * 2^12 is an integer + // then: + // 10^(x) = 2^hi * 2^(mid1) * 2^(mid2) * 10^(lo). + // With this formula: + // - multiplying by 2^hi is exact and cheap, simply by adding the exponent + // field. + // - 2^(mid1) and 2^(mid2) are stored in 2 x 64-element tables. + // - 10^(lo) ~ 1 + a0*lo + a1 * lo^2 + ... + // + // We compute (hi + mid1 + mid2) together by perform the rounding on + // x * log2(10) * 2^12. + // Since |x| < |log10(2^-1075)| < 2^9, + // |x * 2^12| < 2^9 * 2^12 < 2^21, + // So we can fit the rounded result round(x * 2^12) in int32_t. + // Thus, the goal is to be able to use an additional addition and fixed width + // shift to get an int32_t representing round(x * 2^12). + // + // Assuming int32_t using 2-complement representation, since the mantissa part + // of a double precision is unsigned with the leading bit hidden, if we add an + // extra constant C = 2^e1 + 2^e2 with e1 > e2 >= 2^23 to the product, the + // part that are < 2^e2 in resulted mantissa of (x*2^12*L2E + C) can be + // considered as a proper 2-complement representations of x*2^12. + // + // One small problem with this approach is that the sum (x*2^12 + C) in + // double precision is rounded to the least significant bit of the dorminant + // factor C. In order to minimize the rounding errors from this addition, we + // want to minimize e1. Another constraint that we want is that after + // shifting the mantissa so that the least significant bit of int32_t + // corresponds to the unit bit of (x*2^12*L2E), the sign is correct without + // any adjustment. So combining these 2 requirements, we can choose + // C = 2^33 + 2^32, so that the sign bit corresponds to 2^31 bit, and hence + // after right shifting the mantissa, the resulting int32_t has correct sign. + // With this choice of C, the number of mantissa bits we need to shift to the + // right is: 52 - 33 = 19. + // + // Moreover, since the integer right shifts are equivalent to rounding down, + // we can add an extra 0.5 so that it will become round-to-nearest, tie-to- + // +infinity. So in particular, we can compute: + // hmm = x * 2^12 + C, + // where C = 2^33 + 2^32 + 2^-1, then if + // k = int32_t(lower 51 bits of double(x * 2^12 + C) >> 19), + // the reduced argument: + // lo = x - log10(2) * 2^-12 * k is bounded by: + // |lo| = |x - log10(2) * 2^-12 * k| + // = log10(2) * 2^-12 * | x * log2(10) * 2^12 - k | + // <= log10(2) * 2^-12 * (2^-1 + 2^-19) + // < 1.5 * 2^-2 * (2^-13 + 2^-31) + // = 1.5 * (2^-15 * 2^-31) + // + // Finally, notice that k only uses the mantissa of x * 2^12, so the + // exponent 2^12 is not needed. So we can simply define + // C = 2^(33 - 12) + 2^(32 - 12) + 2^(-13 - 12), and + // k = int32_t(lower 51 bits of double(x + C) >> 19). + + // Rounding errors <= 2^-31. + double tmp = fputil::multiply_add(x, LOG2_10, 0x1.8000'0000'4p21); + int k = static_cast(cpp::bit_cast(tmp) >> 19); + double kd = static_cast(k); + + uint32_t idx1 = (k >> 6) & 0x3f; + uint32_t idx2 = k & 0x3f; + + int hi = k >> 12; + + DoubleDouble exp_mid1{EXP2_MID1[idx1].mid, EXP2_MID1[idx1].hi}; + DoubleDouble exp_mid2{EXP2_MID2[idx2].mid, EXP2_MID2[idx2].hi}; + DoubleDouble exp_mid = fputil::quick_mult(exp_mid1, exp_mid2); + + // |dx| < 1.5 * 2^-15 + 2^-31 < 2^-14 + double lo_h = fputil::multiply_add(kd, MLOG10_2_EXP2_M12_HI, x); // exact + double dx = fputil::multiply_add(kd, MLOG10_2_EXP2_M12_MID, lo_h); + + // We use the degree-4 polynomial to approximate 10^(lo): + // 10^(lo) ~ 1 + a0 * lo + a1 * lo^2 + a2 * lo^3 + a3 * lo^4 + // = 1 + lo * P(lo) + // So that the errors are bounded by: + // |P(lo) - (10^lo - 1)/lo| < |lo|^4 / 64 < 2^(-13 * 4) / 64 = 2^-58 + // Let P_ be an evaluation of P where all intermediate computations are in + // double precision. Using either Horner's or Estrin's schemes, the evaluated + // errors can be bounded by: + // |P_(lo) - P(lo)| < 2^-51 + // => |lo * P_(lo) - (2^lo - 1) | < 2^-65 + // => 2^(mid1 + mid2) * |lo * P_(lo) - expm1(lo)| < 2^-64. + // Since we approximate + // 2^(mid1 + mid2) ~ exp_mid.hi + exp_mid.lo, + // We use the expression: + // (exp_mid.hi + exp_mid.lo) * (1 + dx * P_(dx)) ~ + // ~ exp_mid.hi + (exp_mid.hi * dx * P_(dx) + exp_mid.lo) + // with errors bounded by 2^-64. + + double mid_lo = dx * exp_mid.hi; + + // Approximate (10^dx - 1)/dx ~ 1 + a0*dx + a1*dx^2 + a2*dx^3 + a3*dx^4. + double p = exp10_poly_approx_d(dx); + + double lo = fputil::multiply_add(p, mid_lo, exp_mid.lo); + +#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS + int64_t exp_hi = static_cast(hi) << FPBits::FRACTION_LEN; + double r = + cpp::bit_cast(exp_hi + cpp::bit_cast(exp_mid.hi + lo)); + return r; +#else + double upper = exp_mid.hi + (lo + EXP10_ERR_D); + double lower = exp_mid.hi + (lo - EXP10_ERR_D); + + if (LIBC_LIKELY(upper == lower)) { + // To multiply by 2^hi, a fast way is to simply add hi to the exponent + // field. + int64_t exp_hi = static_cast(hi) << FPBits::FRACTION_LEN; + double r = cpp::bit_cast(exp_hi + cpp::bit_cast(upper)); + return r; + } + + // Exact outputs when x = 1, 2, ..., 22 + hard to round with x = 23. + // Quick check mask: 0x800f'ffffU = ~(bits of 1.0 | ... | bits of 23.0) + if (LIBC_UNLIKELY((x_u & 0x8000'ffff'ffff'ffffULL) == 0ULL)) { + switch (x_u) { + case 0x3ff0000000000000: // x = 1.0 + return 10.0; + case 0x4000000000000000: // x = 2.0 + return 100.0; + case 0x4008000000000000: // x = 3.0 + return 1'000.0; + case 0x4010000000000000: // x = 4.0 + return 10'000.0; + case 0x4014000000000000: // x = 5.0 + return 100'000.0; + case 0x4018000000000000: // x = 6.0 + return 1'000'000.0; + case 0x401c000000000000: // x = 7.0 + return 10'000'000.0; + case 0x4020000000000000: // x = 8.0 + return 100'000'000.0; + case 0x4022000000000000: // x = 9.0 + return 1'000'000'000.0; + case 0x4024000000000000: // x = 10.0 + return 10'000'000'000.0; + case 0x4026000000000000: // x = 11.0 + return 100'000'000'000.0; + case 0x4028000000000000: // x = 12.0 + return 1'000'000'000'000.0; + case 0x402a000000000000: // x = 13.0 + return 10'000'000'000'000.0; + case 0x402c000000000000: // x = 14.0 + return 100'000'000'000'000.0; + case 0x402e000000000000: // x = 15.0 + return 1'000'000'000'000'000.0; + case 0x4030000000000000: // x = 16.0 + return 10'000'000'000'000'000.0; + case 0x4031000000000000: // x = 17.0 + return 100'000'000'000'000'000.0; + case 0x4032000000000000: // x = 18.0 + return 1'000'000'000'000'000'000.0; + case 0x4033000000000000: // x = 19.0 + return 10'000'000'000'000'000'000.0; + case 0x4034000000000000: // x = 20.0 + return 100'000'000'000'000'000'000.0; + case 0x4035000000000000: // x = 21.0 + return 1'000'000'000'000'000'000'000.0; + case 0x4036000000000000: // x = 22.0 + return 10'000'000'000'000'000'000'000.0; + case 0x4037000000000000: // x = 23.0 + return 0x1.52d02c7e14af6p76 + x; + } + } + + // Use double-double + DoubleDouble r_dd = exp10_double_double(x, kd, exp_mid); + + double upper_dd = r_dd.hi + (r_dd.lo + EXP10_ERR_DD); + double lower_dd = r_dd.hi + (r_dd.lo - EXP10_ERR_DD); + + if (LIBC_LIKELY(upper_dd == lower_dd)) { + // To multiply by 2^hi, a fast way is to simply add hi to the exponent + // field. + int64_t exp_hi = static_cast(hi) << FPBits::FRACTION_LEN; + double r = cpp::bit_cast(exp_hi + cpp::bit_cast(upper_dd)); + return r; + } + + // Use 128-bit precision + Float128 r_f128 = exp10_f128(x, kd, idx1, idx2); + + return static_cast(r_f128); +#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS +} + +} // namespace math + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_EXP10_H diff --git a/libc/src/__support/math/exp10_float16_constants.h b/libc/src/__support/math/exp10_float16_constants.h new file mode 100644 index 0000000000000..f5928db740ee4 --- /dev/null +++ b/libc/src/__support/math/exp10_float16_constants.h @@ -0,0 +1,43 @@ +//===-- Constants for exp10f16 function -------------------------*- 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_LIBC_SRC___SUPPORT_MATH_EXP10_FLOAT16_CONSTANTS_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_EXP10_FLOAT16_CONSTANTS_H + +#include "include/llvm-libc-macros/float16-macros.h" +#include + +#ifdef LIBC_TYPES_HAS_FLOAT16 + +#include "src/__support/CPP/array.h" + +namespace LIBC_NAMESPACE_DECL { + +// Generated by Sollya with the following commands: +// > display = hexadecimal; +// > for i from 0 to 7 do printsingle(round(2^(i * 2^-3), SG, RN)); +static constexpr cpp::array EXP2_MID_BITS = { + 0x3f80'0000U, 0x3f8b'95c2U, 0x3f98'37f0U, 0x3fa5'fed7U, + 0x3fb5'04f3U, 0x3fc5'672aU, 0x3fd7'44fdU, 0x3fea'c0c7U, +}; + +// Generated by Sollya with the following commands: +// > display = hexadecimal; +// > round(log2(10), SG, RN); +static constexpr float LOG2F_10 = 0x1.a934fp+1f; + +// Generated by Sollya with the following commands: +// > display = hexadecimal; +// > round(log10(2), SG, RN); +static constexpr float LOG10F_2 = 0x1.344136p-2f; + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LIBC_TYPES_HAS_FLOAT16 + +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_EXP10F16_H diff --git a/libc/src/math/generic/exp10f_impl.h b/libc/src/__support/math/exp10f.h similarity index 91% rename from libc/src/math/generic/exp10f_impl.h rename to libc/src/__support/math/exp10f.h index 975fd01a0a25c..807b4f0d6c109 100644 --- a/libc/src/math/generic/exp10f_impl.h +++ b/libc/src/__support/math/exp10f.h @@ -1,4 +1,4 @@ -//===-- Single-precision 10^x function ------------------------------------===// +//===-- Implementation header for exp10f ------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,22 +6,21 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_SRC_MATH_GENERIC_EXP10F_IMPL_H -#define LLVM_LIBC_SRC_MATH_GENERIC_EXP10F_IMPL_H +#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_EXP10F_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_EXP10F_H -#include "explogxf.h" +#include "exp10f_utils.h" #include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/multiply_add.h" #include "src/__support/FPUtil/rounding_mode.h" -#include "src/__support/common.h" #include "src/__support/macros/config.h" #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY namespace LIBC_NAMESPACE_DECL { -namespace generic { +namespace math { -LIBC_INLINE float exp10f(float x) { +static constexpr float exp10f(float x) { using FPBits = typename fputil::FPBits; FPBits xbits(x); @@ -132,7 +131,7 @@ LIBC_INLINE float exp10f(float x) { return static_cast(multiply_add(p, lo2 * rr.mh, c0 * rr.mh)); } -} // namespace generic +} // namespace math } // namespace LIBC_NAMESPACE_DECL -#endif // LLVM_LIBC_SRC_MATH_GENERIC_EXP10F_IMPL_H +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_EXP10F_H diff --git a/libc/src/__support/math/exp10f16.h b/libc/src/__support/math/exp10f16.h new file mode 100644 index 0000000000000..0d8b125348844 --- /dev/null +++ b/libc/src/__support/math/exp10f16.h @@ -0,0 +1,141 @@ +//===-- Implementation header for exp10f16 ----------------------*- 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_LIBC_SRC___SUPPORT_MATH_EXP10F16_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_EXP10F16_H + +#include "include/llvm-libc-macros/float16-macros.h" + +#ifdef LIBC_TYPES_HAS_FLOAT16 + +#include "exp10f16_utils.h" +#include "src/__support/FPUtil/FEnvImpl.h" +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/cast.h" +#include "src/__support/FPUtil/except_value_utils.h" +#include "src/__support/FPUtil/rounding_mode.h" +#include "src/__support/macros/config.h" +#include "src/__support/macros/optimization.h" +#include "src/__support/macros/properties/cpu_features.h" + +namespace LIBC_NAMESPACE_DECL { + +namespace math { + +#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS +#ifdef LIBC_TARGET_CPU_HAS_FMA_FLOAT +static constexpr size_t N_EXP10F16_EXCEPTS = 5; +#else +static constexpr size_t N_EXP10F16_EXCEPTS = 8; +#endif + +static constexpr fputil::ExceptValues + EXP10F16_EXCEPTS = {{ + // x = 0x1.8f4p-2, exp10f16(x) = 0x1.3ap+1 (RZ) + {0x363dU, 0x40e8U, 1U, 0U, 1U}, + // x = 0x1.95cp-2, exp10f16(x) = 0x1.3ecp+1 (RZ) + {0x3657U, 0x40fbU, 1U, 0U, 0U}, + // x = -0x1.018p-4, exp10f16(x) = 0x1.bbp-1 (RZ) + {0xac06U, 0x3aecU, 1U, 0U, 0U}, + // x = -0x1.c28p+0, exp10f16(x) = 0x1.1ccp-6 (RZ) + {0xbf0aU, 0x2473U, 1U, 0U, 0U}, + // x = -0x1.e1cp+1, exp10f16(x) = 0x1.694p-13 (RZ) + {0xc387U, 0x09a5U, 1U, 0U, 0U}, +#ifndef LIBC_TARGET_CPU_HAS_FMA_FLOAT + // x = 0x1.0cp+1, exp10f16(x) = 0x1.f04p+6 (RZ) + {0x4030U, 0x57c1U, 1U, 0U, 1U}, + // x = 0x1.1b8p+1, exp10f16(x) = 0x1.47cp+7 (RZ) + {0x406eU, 0x591fU, 1U, 0U, 1U}, + // x = 0x1.1b8p+2, exp10f16(x) = 0x1.a4p+14 (RZ) + {0x446eU, 0x7690U, 1U, 0U, 1U}, +#endif + }}; +#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS + +static constexpr float16 exp10f16(float16 x) { + using FPBits = fputil::FPBits; + FPBits x_bits(x); + + uint16_t x_u = x_bits.uintval(); + uint16_t x_abs = x_u & 0x7fffU; + + // When |x| >= 5, or x is NaN. + if (LIBC_UNLIKELY(x_abs >= 0x4500U)) { + // exp10(NaN) = NaN + if (x_bits.is_nan()) { + if (x_bits.is_signaling_nan()) { + fputil::raise_except_if_required(FE_INVALID); + return FPBits::quiet_nan().get_val(); + } + + return x; + } + + // When x >= 5. + if (x_bits.is_pos()) { + // exp10(+inf) = +inf + if (x_bits.is_inf()) + return FPBits::inf().get_val(); + + switch (fputil::quick_get_round()) { + case FE_TONEAREST: + case FE_UPWARD: + fputil::set_errno_if_required(ERANGE); + fputil::raise_except_if_required(FE_OVERFLOW); + return FPBits::inf().get_val(); + default: + return FPBits::max_normal().get_val(); + } + } + + // When x <= -8. + if (x_u >= 0xc800U) { + // exp10(-inf) = +0 + if (x_bits.is_inf()) + return FPBits::zero().get_val(); + + fputil::set_errno_if_required(ERANGE); + fputil::raise_except_if_required(FE_UNDERFLOW | FE_INEXACT); + + if (fputil::fenv_is_round_up()) + return FPBits::min_subnormal().get_val(); + return FPBits::zero().get_val(); + } + } + + // When x is 1, 2, 3, or 4. These are hard-to-round cases with exact results. + if (LIBC_UNLIKELY((x_u & ~(0x3c00U | 0x4000U | 0x4200U | 0x4400U)) == 0)) { + switch (x_u) { + case 0x3c00U: // x = 1.0f16 + return fputil::cast(10.0); + case 0x4000U: // x = 2.0f16 + return fputil::cast(100.0); + case 0x4200U: // x = 3.0f16 + return fputil::cast(1'000.0); + case 0x4400U: // x = 4.0f16 + return fputil::cast(10'000.0); + } + } + +#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS + if (auto r = EXP10F16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value())) + return r.value(); +#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS + + // 10^x = 2^((hi + mid) * log2(10)) * 10^lo + auto [exp2_hi_mid, exp10_lo] = exp10_range_reduction(x); + return fputil::cast(exp2_hi_mid * exp10_lo); +} + +} // namespace math + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LIBC_TYPES_HAS_FLOAT16 + +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_EXP10F16_H diff --git a/libc/src/__support/math/exp10f16_utils.h b/libc/src/__support/math/exp10f16_utils.h new file mode 100644 index 0000000000000..bffb81ba606bb --- /dev/null +++ b/libc/src/__support/math/exp10f16_utils.h @@ -0,0 +1,64 @@ +//===-- Common utils for exp10f16 -------------------------------*- 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_LIBC_SRC___SUPPORT_MATH_EXP10F16_UTILS_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_EXP10F16_UTILS_H + +#include "include/llvm-libc-macros/float16-macros.h" + +#ifdef LIBC_TYPES_HAS_FLOAT16 + +#include "exp10_float16_constants.h" +#include "expf16_utils.h" +#include "src/__support/FPUtil/FPBits.h" + +namespace LIBC_NAMESPACE_DECL { + +LIBC_INLINE static constexpr ExpRangeReduction +exp10_range_reduction(float16 x) { + // For -8 < x < 5, to compute 10^x, we perform the following range reduction: + // find hi, mid, lo, such that: + // x = (hi + mid) * log2(10) + lo, in which + // hi is an integer, + // mid * 2^3 is an integer, + // -2^(-4) <= lo < 2^(-4). + // In particular, + // hi + mid = round(x * 2^3) * 2^(-3). + // Then, + // 10^x = 10^(hi + mid + lo) = 2^((hi + mid) * log2(10)) + 10^lo + // We store 2^mid in the lookup table EXP2_MID_BITS, and compute 2^hi * 2^mid + // by adding hi to the exponent field of 2^mid. 10^lo is computed using a + // degree-4 minimax polynomial generated by Sollya. + + float xf = x; + float kf = fputil::nearest_integer(xf * (LOG2F_10 * 0x1.0p+3f)); + int x_hi_mid = static_cast(kf); + unsigned x_hi = static_cast(x_hi_mid) >> 3; + unsigned x_mid = static_cast(x_hi_mid) & 0x7; + // lo = x - (hi + mid) = round(x * 2^3 * log2(10)) * log10(2) * (-2^(-3)) + x + float lo = fputil::multiply_add(kf, LOG10F_2 * -0x1.0p-3f, xf); + + uint32_t exp2_hi_mid_bits = + EXP2_MID_BITS[x_mid] + + static_cast(x_hi << fputil::FPBits::FRACTION_LEN); + float exp2_hi_mid = fputil::FPBits(exp2_hi_mid_bits).get_val(); + // Degree-4 minimax polynomial generated by Sollya with the following + // commands: + // > display = hexadecimal; + // > P = fpminimax((10^x - 1)/x, 3, [|SG...|], [-2^-4, 2^-4]); + // > 1 + x * P; + float exp10_lo = fputil::polyeval(lo, 0x1p+0f, 0x1.26bb14p+1f, 0x1.53526p+1f, + 0x1.04b434p+1f, 0x1.2bcf9ep+0f); + return {exp2_hi_mid, exp10_lo}; +} + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LIBC_TYPES_HAS_FLOAT16 + +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_EXP10F16_UTILS_H diff --git a/libc/src/__support/math/exp10f_utils.h b/libc/src/__support/math/exp10f_utils.h new file mode 100644 index 0000000000000..c30def9d62db2 --- /dev/null +++ b/libc/src/__support/math/exp10f_utils.h @@ -0,0 +1,157 @@ +//===-- Common utils for exp10f ---------------------------------*- 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_LIBC_SRC___SUPPORT_MATH_EXP10F_UTILS_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_EXP10F_UTILS_H + +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/PolyEval.h" +#include "src/__support/FPUtil/nearest_integer.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +struct ExpBase { + // Base = e + static constexpr int MID_BITS = 5; + static constexpr int MID_MASK = (1 << MID_BITS) - 1; + // log2(e) * 2^5 + static constexpr double LOG2_B = 0x1.71547652b82fep+0 * (1 << MID_BITS); + // High and low parts of -log(2) * 2^(-5) + static constexpr double M_LOGB_2_HI = -0x1.62e42fefa0000p-1 / (1 << MID_BITS); + static constexpr double M_LOGB_2_LO = + -0x1.cf79abc9e3b3ap-40 / (1 << MID_BITS); + // Look up table for bit fields of 2^(i/32) for i = 0..31, generated by Sollya + // with: + // > for i from 0 to 31 do printdouble(round(2^(i/32), D, RN)); + static constexpr int64_t EXP_2_MID[1 << MID_BITS] = { + 0x3ff0000000000000, 0x3ff059b0d3158574, 0x3ff0b5586cf9890f, + 0x3ff11301d0125b51, 0x3ff172b83c7d517b, 0x3ff1d4873168b9aa, + 0x3ff2387a6e756238, 0x3ff29e9df51fdee1, 0x3ff306fe0a31b715, + 0x3ff371a7373aa9cb, 0x3ff3dea64c123422, 0x3ff44e086061892d, + 0x3ff4bfdad5362a27, 0x3ff5342b569d4f82, 0x3ff5ab07dd485429, + 0x3ff6247eb03a5585, 0x3ff6a09e667f3bcd, 0x3ff71f75e8ec5f74, + 0x3ff7a11473eb0187, 0x3ff82589994cce13, 0x3ff8ace5422aa0db, + 0x3ff93737b0cdc5e5, 0x3ff9c49182a3f090, 0x3ffa5503b23e255d, + 0x3ffae89f995ad3ad, 0x3ffb7f76f2fb5e47, 0x3ffc199bdd85529c, + 0x3ffcb720dcef9069, 0x3ffd5818dcfba487, 0x3ffdfc97337b9b5f, + 0x3ffea4afa2a490da, 0x3fff50765b6e4540, + }; + + // Approximating e^dx with degree-5 minimax polynomial generated by Sollya: + // > Q = fpminimax(expm1(x)/x, 4, [|1, D...|], [-log(2)/64, log(2)/64]); + // Then: + // e^dx ~ P(dx) = 1 + dx + COEFFS[0] * dx^2 + ... + COEFFS[3] * dx^5. + static constexpr double COEFFS[4] = { + 0x1.ffffffffe5bc8p-2, 0x1.555555555cd67p-3, 0x1.5555c2a9b48b4p-5, + 0x1.11112a0e34bdbp-7}; + + LIBC_INLINE static double powb_lo(double dx) { + using fputil::multiply_add; + double dx2 = dx * dx; + double c0 = 1.0 + dx; + // c1 = COEFFS[0] + COEFFS[1] * dx + double c1 = multiply_add(dx, ExpBase::COEFFS[1], ExpBase::COEFFS[0]); + // c2 = COEFFS[2] + COEFFS[3] * dx + double c2 = multiply_add(dx, ExpBase::COEFFS[3], ExpBase::COEFFS[2]); + // r = c4 + c5 * dx^4 + // = 1 + dx + COEFFS[0] * dx^2 + ... + COEFFS[5] * dx^7 + return fputil::polyeval(dx2, c0, c1, c2); + } +}; + +struct Exp10Base : public ExpBase { + // log2(10) * 2^5 + static constexpr double LOG2_B = 0x1.a934f0979a371p1 * (1 << MID_BITS); + // High and low parts of -log10(2) * 2^(-5). + // Notice that since |x * log2(10)| < 150: + // |k| = |round(x * log2(10) * 2^5)| < 2^8 * 2^5 = 2^13 + // So when the FMA instructions are not available, in order for the product + // k * M_LOGB_2_HI + // to be exact, we only store the high part of log10(2) up to 38 bits + // (= 53 - 15) of precision. + // It is generated by Sollya with: + // > round(log10(2), 44, RN); + static constexpr double M_LOGB_2_HI = -0x1.34413509f8p-2 / (1 << MID_BITS); + // > round(log10(2) - 0x1.34413509f8p-2, D, RN); + static constexpr double M_LOGB_2_LO = 0x1.80433b83b532ap-44 / (1 << MID_BITS); + + // Approximating 10^dx with degree-5 minimax polynomial generated by Sollya: + // > Q = fpminimax((10^x - 1)/x, 4, [|D...|], [-log10(2)/2^6, log10(2)/2^6]); + // Then: + // 10^dx ~ P(dx) = 1 + COEFFS[0] * dx + ... + COEFFS[4] * dx^5. + static constexpr double COEFFS[5] = {0x1.26bb1bbb55515p1, 0x1.53524c73bd3eap1, + 0x1.0470591dff149p1, 0x1.2bd7c0a9fbc4dp0, + 0x1.1429e74a98f43p-1}; + + static double powb_lo(double dx) { + using fputil::multiply_add; + double dx2 = dx * dx; + // c0 = 1 + COEFFS[0] * dx + double c0 = multiply_add(dx, Exp10Base::COEFFS[0], 1.0); + // c1 = COEFFS[1] + COEFFS[2] * dx + double c1 = multiply_add(dx, Exp10Base::COEFFS[2], Exp10Base::COEFFS[1]); + // c2 = COEFFS[3] + COEFFS[4] * dx + double c2 = multiply_add(dx, Exp10Base::COEFFS[4], Exp10Base::COEFFS[3]); + // r = c0 + dx^2 * (c1 + c2 * dx^2) + // = c0 + c1 * dx^2 + c2 * dx^4 + // = 1 + COEFFS[0] * dx + ... + COEFFS[4] * dx^5. + return fputil::polyeval(dx2, c0, c1, c2); + } +}; + +// Output of range reduction for exp_b: (2^(mid + hi), lo) +// where: +// b^x = 2^(mid + hi) * b^lo +struct exp_b_reduc_t { + double mh; // 2^(mid + hi) + double lo; +}; + +// The function correctly calculates b^x value with at least float precision +// in a limited range. +// Range reduction: +// b^x = 2^(hi + mid) * b^lo +// where: +// x = (hi + mid) * log_b(2) + lo +// hi is an integer, +// 0 <= mid * 2^MID_BITS < 2^MID_BITS is an integer +// -2^(-MID_BITS - 1) <= lo * log2(b) <= 2^(-MID_BITS - 1) +// Base class needs to provide the following constants: +// - MID_BITS : number of bits after decimal points used for mid +// - MID_MASK : 2^MID_BITS - 1, mask to extract mid bits +// - LOG2_B : log2(b) * 2^MID_BITS for scaling +// - M_LOGB_2_HI : high part of -log_b(2) * 2^(-MID_BITS) +// - M_LOGB_2_LO : low part of -log_b(2) * 2^(-MID_BITS) +// - EXP_2_MID : look up table for bit fields of 2^mid +// Return: +// { 2^(hi + mid), lo } +template +LIBC_INLINE static constexpr exp_b_reduc_t exp_b_range_reduc(float x) { + double xd = static_cast(x); + // kd = round((hi + mid) * log2(b) * 2^MID_BITS) + double kd = fputil::nearest_integer(Base::LOG2_B * xd); + // k = round((hi + mid) * log2(b) * 2^MID_BITS) + int k = static_cast(kd); + // hi = floor(kd * 2^(-MID_BITS)) + // exp_hi = shift hi to the exponent field of double precision. + uint64_t exp_hi = static_cast(k >> Base::MID_BITS) + << fputil::FPBits::FRACTION_LEN; + // mh = 2^hi * 2^mid + // mh_bits = bit field of mh + uint64_t mh_bits = Base::EXP_2_MID[k & Base::MID_MASK] + exp_hi; + double mh = fputil::FPBits(mh_bits).get_val(); + // dx = lo = x - (hi + mid) * log(2) + double dx = fputil::multiply_add( + kd, Base::M_LOGB_2_LO, fputil::multiply_add(kd, Base::M_LOGB_2_HI, xd)); + return {mh, dx}; +} + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_EXP10F_UTILS_H diff --git a/libc/src/math/generic/inv_trigf_utils.cpp b/libc/src/__support/math/inv_trigf_utils.h similarity index 56% rename from libc/src/math/generic/inv_trigf_utils.cpp rename to libc/src/__support/math/inv_trigf_utils.h index f23028bb86b5c..4a8fbeca93e49 100644 --- a/libc/src/math/generic/inv_trigf_utils.cpp +++ b/libc/src/__support/math/inv_trigf_utils.h @@ -1,4 +1,4 @@ -//===-- Single-precision general exp/log functions ------------------------===// +//===-- Single-precision general inverse trigonometric functions ----------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,11 +6,22 @@ // //===----------------------------------------------------------------------===// -#include "inv_trigf_utils.h" +#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_INV_TRIGF_UTILS_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_INV_TRIGF_UTILS_H + +#include "src/__support/FPUtil/PolyEval.h" +#include "src/__support/FPUtil/multiply_add.h" +#include "src/__support/common.h" #include "src/__support/macros/config.h" namespace LIBC_NAMESPACE_DECL { +namespace inv_trigf_utils_internal { + +// PI and PI / 2 +static constexpr double M_MATH_PI = 0x1.921fb54442d18p+1; +static constexpr double M_MATH_PI_2 = 0x1.921fb54442d18p+0; + // Polynomial approximation for 0 <= x <= 1: // atan(x) ~ atan((i/16) + (x - (i/16)) * Q(x - i/16) // = P(x - i/16) @@ -29,7 +40,7 @@ namespace LIBC_NAMESPACE_DECL { // Notice that degree-7 is good enough for atanf, but degree-8 helps reduce the // error bounds for atan2f's fast pass 16 times, and it does not affect the // performance of atanf much. -double ATAN_COEFFS[17][9] = { +static constexpr double ATAN_COEFFS[17][9] = { {0.0, 1.0, 0x1.3f8d76d26d61bp-47, -0x1.5555555574cd8p-2, 0x1.0dde5d06878eap-29, 0x1.99997738acc77p-3, 0x1.2c43eac9797cap-16, -0x1.25fb020007dbdp-3, 0x1.c1b6c31d7b0aep-7}, @@ -83,4 +94,91 @@ double ATAN_COEFFS[17][9] = { 0x1.555e31a1e15e9p-6, -0x1.245240d65e629p-7, -0x1.fa9ba66478903p-11}, }; +// Look-up table for atan(k/16) with k = 0..16. +static constexpr double ATAN_K_OVER_16[17] = { + 0.0, + 0x1.ff55bb72cfdeap-5, + 0x1.fd5ba9aac2f6ep-4, + 0x1.7b97b4bce5b02p-3, + 0x1.f5b75f92c80ddp-3, + 0x1.362773707ebccp-2, + 0x1.6f61941e4def1p-2, + 0x1.a64eec3cc23fdp-2, + 0x1.dac670561bb4fp-2, + 0x1.0657e94db30dp-1, + 0x1.1e00babdefeb4p-1, + 0x1.345f01cce37bbp-1, + 0x1.4978fa3269ee1p-1, + 0x1.5d58987169b18p-1, + 0x1.700a7c5784634p-1, + 0x1.819d0b7158a4dp-1, + 0x1.921fb54442d18p-1, +}; + +// For |x| <= 1/32 and 0 <= i <= 16, return Q(x) such that: +// Q(x) ~ (atan(x + i/16) - atan(i/16)) / x. +LIBC_INLINE static double atan_eval(double x, unsigned i) { + double x2 = x * x; + + double c0 = fputil::multiply_add(x, ATAN_COEFFS[i][2], ATAN_COEFFS[i][1]); + double c1 = fputil::multiply_add(x, ATAN_COEFFS[i][4], ATAN_COEFFS[i][3]); + double c2 = fputil::multiply_add(x, ATAN_COEFFS[i][6], ATAN_COEFFS[i][5]); + double c3 = fputil::multiply_add(x, ATAN_COEFFS[i][8], ATAN_COEFFS[i][7]); + + double x4 = x2 * x2; + double d1 = fputil::multiply_add(x2, c1, c0); + double d2 = fputil::multiply_add(x2, c3, c2); + double p = fputil::multiply_add(x4, d2, d1); + return p; +} + +// Evaluate atan without big lookup table. +// atan(n/d) - atan(k/16) = atan((n/d - k/16) / (1 + (n/d) * (k/16))) +// = atan((n - d * k/16)) / (d + n * k/16)) +// So we let q = (n - d * k/16) / (d + n * k/16), +// and approximate with Taylor polynomial: +// atan(q) ~ q - q^3/3 + q^5/5 - q^7/7 + q^9/9 +LIBC_INLINE static double atan_eval_no_table(double num, double den, + double k_over_16) { + double num_r = fputil::multiply_add(den, -k_over_16, num); + double den_r = fputil::multiply_add(num, k_over_16, den); + double q = num_r / den_r; + + constexpr double ATAN_TAYLOR[] = { + -0x1.5555555555555p-2, + 0x1.999999999999ap-3, + -0x1.2492492492492p-3, + 0x1.c71c71c71c71cp-4, + }; + double q2 = q * q; + double q3 = q2 * q; + double q4 = q2 * q2; + double c0 = fputil::multiply_add(q2, ATAN_TAYLOR[1], ATAN_TAYLOR[0]); + double c1 = fputil::multiply_add(q2, ATAN_TAYLOR[3], ATAN_TAYLOR[2]); + double d = fputil::multiply_add(q4, c1, c0); + return fputil::multiply_add(q3, d, q); +} + +// > Q = fpminimax(asin(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20|], +// [|1, D...|], [0, 0.5]); +static constexpr double ASIN_COEFFS[10] = { + 0x1.5555555540fa1p-3, 0x1.333333512edc2p-4, 0x1.6db6cc1541b31p-5, + 0x1.f1caff324770ep-6, 0x1.6e43899f5f4f4p-6, 0x1.1f847cf652577p-6, + 0x1.9b60f47f87146p-7, 0x1.259e2634c494fp-6, -0x1.df946fa875ddp-8, + 0x1.02311ecf99c28p-5}; + +// Evaluate P(x^2) - 1, where P(x^2) ~ asin(x)/x +LIBC_INLINE static double asin_eval(double xsq) { + double x4 = xsq * xsq; + double r1 = fputil::polyeval(x4, ASIN_COEFFS[0], ASIN_COEFFS[2], + ASIN_COEFFS[4], ASIN_COEFFS[6], ASIN_COEFFS[8]); + double r2 = fputil::polyeval(x4, ASIN_COEFFS[1], ASIN_COEFFS[3], + ASIN_COEFFS[5], ASIN_COEFFS[7], ASIN_COEFFS[9]); + return fputil::multiply_add(xsq, r2, r1); +} + +} // namespace inv_trigf_utils_internal + } // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_INV_TRIGF_UTILS_H diff --git a/libc/src/__support/wchar/mbrtowc.cpp b/libc/src/__support/wchar/mbrtowc.cpp index 90ba934c42b69..0f730d6e6dbec 100644 --- a/libc/src/__support/wchar/mbrtowc.cpp +++ b/libc/src/__support/wchar/mbrtowc.cpp @@ -37,7 +37,8 @@ ErrorOr mbrtowc(wchar_t *__restrict pwc, const char *__restrict s, } auto wc = char_conv.pop_utf32(); if (wc.has_value()) { - *pwc = wc.value(); + if (pwc != nullptr) + *pwc = wc.value(); // null terminator -> return 0 if (wc.value() == L'\0') return 0; diff --git a/libc/src/__support/wchar/string_converter.h b/libc/src/__support/wchar/string_converter.h index 0635bc57bf3e2..869ebdfc8b390 100644 --- a/libc/src/__support/wchar/string_converter.h +++ b/libc/src/__support/wchar/string_converter.h @@ -56,6 +56,9 @@ template class StringConverter { // TODO: following functions are almost identical // look into templating CharacterConverter pop functions ErrorOr popUTF32() { + if (num_to_write == 0) + return Error(-1); + if (cr.isEmpty() || src_idx == 0) { auto src_elements_read = pushFullCharacter(); if (!src_elements_read.has_value()) @@ -79,6 +82,9 @@ template class StringConverter { } ErrorOr popUTF8() { + if (num_to_write == 0) + return Error(-1); + if (cr.isEmpty() || src_idx == 0) { auto src_elements_read = pushFullCharacter(); if (!src_elements_read.has_value()) diff --git a/libc/src/math/docs/add_math_function.md b/libc/src/math/docs/add_math_function.md index daaf1a3ec5639..d2c85ecf7d9b7 100644 --- a/libc/src/math/docs/add_math_function.md +++ b/libc/src/math/docs/add_math_function.md @@ -183,8 +183,8 @@ implementation (which is very often glibc). - Build and Run exhaustive test (might take hours to run): ``` - $ ninja libc.test.src.math.exhaustive._test - $ projects/libc/test/src/math/exhaustive/libc.test.src.math.exhaustive._test + $ ninja libc.test.src.math.exhaustive._test.__unit__ + $ projects/libc/test/src/math/exhaustive/libc.test.src.math.exhaustive._test.__unit__ ``` - Build and Run performance test: diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index b59beacd94143..408f99ef30760 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -358,7 +358,6 @@ add_entrypoint_object( libc.src.__support.FPUtil.fp_bits libc.src.__support.FPUtil.except_value_utils libc.src.__support.FPUtil.fma - libc.src.__support.FPUtil.multiply_add libc.src.__support.FPUtil.polyeval libc.src.__support.macros.optimization ) @@ -448,7 +447,6 @@ add_entrypoint_object( libc.src.__support.FPUtil.fenv_impl libc.src.__support.FPUtil.fp_bits libc.src.__support.FPUtil.fma - libc.src.__support.FPUtil.multiply_add libc.src.__support.FPUtil.polyeval libc.src.__support.FPUtil.rounding_mode libc.src.__support.macros.optimization @@ -1297,12 +1295,8 @@ add_entrypoint_object( HDRS ../erff.h DEPENDS - .common_constants - libc.src.__support.FPUtil.fp_bits - libc.src.__support.FPUtil.except_value_utils - libc.src.__support.FPUtil.multiply_add - libc.src.__support.FPUtil.polyeval - libc.src.__support.macros.optimization + libc.src.__support.math.erff + libc.src.errno.errno ) add_entrypoint_object( @@ -1457,35 +1451,7 @@ add_entrypoint_object( HDRS ../exp10.h DEPENDS - .common_constants - .explogxf - libc.src.__support.CPP.bit - libc.src.__support.CPP.optional - libc.src.__support.FPUtil.dyadic_float - libc.src.__support.FPUtil.fenv_impl - libc.src.__support.FPUtil.fp_bits - libc.src.__support.FPUtil.multiply_add - libc.src.__support.FPUtil.nearest_integer - libc.src.__support.FPUtil.polyeval - libc.src.__support.FPUtil.rounding_mode - libc.src.__support.FPUtil.triple_double - libc.src.__support.integer_literals - libc.src.__support.macros.optimization - libc.src.errno.errno -) - -add_header_library( - exp10f_impl - HDRS - exp10f_impl.h - DEPENDS - .explogxf - libc.src.__support.FPUtil.fenv_impl - libc.src.__support.FPUtil.fp_bits - libc.src.__support.FPUtil.multiply_add - libc.src.__support.FPUtil.rounding_mode - libc.src.__support.macros.optimization - libc.src.__support.common + libc.src.__support.math.exp10 libc.src.errno.errno ) @@ -1496,7 +1462,8 @@ add_entrypoint_object( HDRS ../exp10f.h DEPENDS - .exp10f_impl + libc.src.__support.math.exp10f + libc.src.errno.errno ) add_entrypoint_object( @@ -1506,20 +1473,8 @@ add_entrypoint_object( HDRS ../exp10f16.h DEPENDS - .expxf16 - libc.hdr.errno_macros - libc.hdr.fenv_macros - libc.src.__support.CPP.array - libc.src.__support.FPUtil.cast - libc.src.__support.FPUtil.except_value_utils - libc.src.__support.FPUtil.fenv_impl - libc.src.__support.FPUtil.fp_bits - libc.src.__support.FPUtil.multiply_add - libc.src.__support.FPUtil.nearest_integer - libc.src.__support.FPUtil.polyeval - libc.src.__support.FPUtil.rounding_mode - libc.src.__support.macros.optimization - libc.src.__support.macros.properties.cpu_features + libc.src.__support.math.exp10f16 + libc.src.errno.errno ) add_entrypoint_object( @@ -1548,7 +1503,6 @@ add_entrypoint_object( HDRS ../exp10m1f16.h DEPENDS - .expxf16 libc.hdr.errno_macros libc.hdr.fenv_macros libc.src.__support.FPUtil.cast @@ -1560,6 +1514,7 @@ add_entrypoint_object( libc.src.__support.FPUtil.rounding_mode libc.src.__support.macros.optimization libc.src.__support.macros.properties.cpu_features + libc.src.__support.math.exp10f16_utils ) add_entrypoint_object( @@ -1633,17 +1588,15 @@ add_entrypoint_object( ../powf.h DEPENDS .common_constants - .exp10f_impl .exp2f_impl .explogxf + libc.src.__support.math.exp10f libc.src.__support.CPP.bit - libc.src.__support.CPP.optional libc.src.__support.FPUtil.fenv_impl libc.src.__support.FPUtil.fp_bits libc.src.__support.FPUtil.multiply_add libc.src.__support.FPUtil.nearest_integer libc.src.__support.FPUtil.polyeval - libc.src.__support.FPUtil.rounding_mode libc.src.__support.FPUtil.sqrt libc.src.__support.FPUtil.triple_double libc.src.__support.macros.optimization @@ -1941,6 +1894,7 @@ add_object_library( common_constants.cpp DEPENDS libc.src.__support.math.exp_constants + libc.src.__support.math.acosh_float_constants libc.src.__support.number_pair ) @@ -3797,21 +3751,15 @@ add_entrypoint_object( ) #TODO: Add errno include to the hyperbolic functions. -add_object_library( +add_header_library( explogxf HDRS explogxf.h - SRCS - explogxf.cpp DEPENDS .common_constants - libc.src.__support.FPUtil.basic_operations - libc.src.__support.FPUtil.fenv_impl - libc.src.__support.FPUtil.multiply_add - libc.src.__support.FPUtil.nearest_integer - libc.src.__support.FPUtil.polyeval - libc.src.__support.common libc.src.__support.math.exp_utils + libc.src.__support.math.acoshf_utils + libc.src.__support.macros.properties.cpu_features libc.src.errno.errno ) @@ -3920,12 +3868,7 @@ add_entrypoint_object( ../acoshf.h DEPENDS .explogxf - libc.src.__support.FPUtil.fenv_impl - libc.src.__support.FPUtil.fp_bits - libc.src.__support.FPUtil.multiply_add - libc.src.__support.FPUtil.polyeval - libc.src.__support.FPUtil.sqrt - libc.src.__support.macros.optimization + libc.src.__support.math.acoshf ) add_entrypoint_object( @@ -3935,18 +3878,8 @@ add_entrypoint_object( HDRS ../acoshf16.h DEPENDS - .explogxf - libc.hdr.errno_macros - libc.hdr.fenv_macros - libc.src.__support.FPUtil.cast - libc.src.__support.FPUtil.except_value_utils - libc.src.__support.FPUtil.fenv_impl - libc.src.__support.FPUtil.fp_bits - libc.src.__support.FPUtil.multiply_add - libc.src.__support.FPUtil.polyeval - libc.src.__support.FPUtil.sqrt - libc.src.__support.macros.optimization - libc.src.__support.macros.properties.types + libc.src.__support.math.acoshf16 + libc.src.errno.errno ) add_entrypoint_object( @@ -3994,6 +3927,7 @@ add_entrypoint_object( DEPENDS .explogxf libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.fenv_impl libc.src.__support.macros.optimization ) @@ -4017,18 +3951,6 @@ add_entrypoint_object( libc.src.__support.macros.properties.types ) -add_object_library( - inv_trigf_utils - HDRS - inv_trigf_utils.h - SRCS - inv_trigf_utils.cpp - DEPENDS - libc.src.__support.FPUtil.multiply_add - libc.src.__support.FPUtil.polyeval - libc.src.__support.common -) - add_entrypoint_object( asinf SRCS @@ -4042,7 +3964,7 @@ add_entrypoint_object( libc.src.__support.FPUtil.polyeval libc.src.__support.FPUtil.sqrt libc.src.__support.macros.optimization - .inv_trigf_utils + libc.src.__support.math.inv_trigf_utils ) add_entrypoint_object( @@ -4064,20 +3986,6 @@ add_entrypoint_object( libc.src.__support.macros.properties.types ) -add_header_library( - asin_utils - HDRS - atan_utils.h - DEPENDS - libc.src.__support.integer_literals - libc.src.__support.FPUtil.double_double - libc.src.__support.FPUtil.dyadic_float - libc.src.__support.FPUtil.multiply_add - libc.src.__support.FPUtil.nearest_integer - libc.src.__support.FPUtil.polyeval - libc.src.__support.macros.optimization -) - add_entrypoint_object( asin SRCS @@ -4085,7 +3993,7 @@ add_entrypoint_object( HDRS ../asin.h DEPENDS - .asin_utils + libc.src.__support.math.asin_utils libc.src.__support.FPUtil.double_double libc.src.__support.FPUtil.dyadic_float libc.src.__support.FPUtil.fenv_impl @@ -4104,13 +4012,7 @@ add_entrypoint_object( HDRS ../acosf.h DEPENDS - libc.src.__support.FPUtil.except_value_utils - libc.src.__support.FPUtil.fp_bits - libc.src.__support.FPUtil.multiply_add - libc.src.__support.FPUtil.polyeval - libc.src.__support.FPUtil.sqrt - libc.src.__support.macros.optimization - .inv_trigf_utils + libc.src.__support.math.acosf ) add_entrypoint_object( @@ -4120,17 +4022,8 @@ add_entrypoint_object( HDRS ../acosf16.h DEPENDS - libc.hdr.errno_macros - libc.hdr.fenv_macros - libc.src.__support.FPUtil.cast - libc.src.__support.FPUtil.except_value_utils - libc.src.__support.FPUtil.fenv_impl - libc.src.__support.FPUtil.fp_bits - libc.src.__support.FPUtil.multiply_add - libc.src.__support.FPUtil.polyeval - libc.src.__support.FPUtil.sqrt - libc.src.__support.macros.optimization - libc.src.__support.macros.properties.types + libc.src.__support.math.acosf16 + libc.src.errno.errno ) add_entrypoint_object( @@ -4140,17 +4033,7 @@ add_entrypoint_object( HDRS ../acos.h DEPENDS - .asin_utils - libc.src.__support.FPUtil.double_double - libc.src.__support.FPUtil.dyadic_float - libc.src.__support.FPUtil.fenv_impl - libc.src.__support.FPUtil.fp_bits - libc.src.__support.FPUtil.multiply_add - libc.src.__support.FPUtil.polyeval - libc.src.__support.FPUtil.sqrt - libc.src.__support.macros.optimization - libc.src.__support.macros.properties.types - libc.src.__support.macros.properties.cpu_features + libc.src.__support.math.acos ) add_entrypoint_object( @@ -4192,7 +4075,6 @@ add_entrypoint_object( HDRS ../atanf.h DEPENDS - .inv_trigf_utils libc.src.__support.FPUtil.except_value_utils libc.src.__support.FPUtil.fp_bits libc.src.__support.FPUtil.multiply_add @@ -4200,6 +4082,7 @@ add_entrypoint_object( libc.src.__support.FPUtil.polyeval libc.src.__support.FPUtil.rounding_mode libc.src.__support.macros.optimization + libc.src.__support.math.inv_trigf_utils ) add_entrypoint_object( @@ -4248,7 +4131,6 @@ add_entrypoint_object( ../atan2f.h atan2f_float.h DEPENDS - .inv_trigf_utils libc.hdr.fenv_macros libc.src.__support.FPUtil.double_double libc.src.__support.FPUtil.fenv_impl @@ -4258,6 +4140,7 @@ add_entrypoint_object( libc.src.__support.FPUtil.polyeval libc.src.__support.FPUtil.rounding_mode libc.src.__support.macros.optimization + libc.src.__support.math.inv_trigf_utils ) add_entrypoint_object( @@ -5059,10 +4942,11 @@ add_header_library( HDRS expxf16.h DEPENDS - libc.src.__support.FPUtil.cast libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.cast libc.src.__support.FPUtil.multiply_add libc.src.__support.FPUtil.nearest_integer libc.src.__support.macros.attributes libc.src.__support.math.expf16_utils + libc.src.__support.math.exp10_float16_constants ) diff --git a/libc/src/math/generic/acos.cpp b/libc/src/math/generic/acos.cpp index c14721faef3ce..3a5964290cdd3 100644 --- a/libc/src/math/generic/acos.cpp +++ b/libc/src/math/generic/acos.cpp @@ -7,272 +7,10 @@ //===----------------------------------------------------------------------===// #include "src/math/acos.h" -#include "asin_utils.h" -#include "src/__support/FPUtil/FEnvImpl.h" -#include "src/__support/FPUtil/FPBits.h" -#include "src/__support/FPUtil/PolyEval.h" -#include "src/__support/FPUtil/double_double.h" -#include "src/__support/FPUtil/dyadic_float.h" -#include "src/__support/FPUtil/multiply_add.h" -#include "src/__support/FPUtil/sqrt.h" -#include "src/__support/macros/config.h" -#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY -#include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA +#include "src/__support/math/acos.h" namespace LIBC_NAMESPACE_DECL { -using DoubleDouble = fputil::DoubleDouble; -using Float128 = fputil::DyadicFloat<128>; - -LLVM_LIBC_FUNCTION(double, acos, (double x)) { - using FPBits = fputil::FPBits; - - FPBits xbits(x); - int x_exp = xbits.get_biased_exponent(); - - // |x| < 0.5. - if (x_exp < FPBits::EXP_BIAS - 1) { - // |x| < 2^-55. - if (LIBC_UNLIKELY(x_exp < FPBits::EXP_BIAS - 55)) { - // When |x| < 2^-55, acos(x) = pi/2 -#if defined(LIBC_MATH_HAS_SKIP_ACCURATE_PASS) - return PI_OVER_TWO.hi; -#else - // Force the evaluation and prevent constant propagation so that it - // is rounded correctly for FE_UPWARD rounding mode. - return (xbits.abs().get_val() + 0x1.0p-160) + PI_OVER_TWO.hi; -#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS - } - -#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS - // acos(x) = pi/2 - asin(x) - // = pi/2 - x * P(x^2) - double p = asin_eval(x * x); - return PI_OVER_TWO.hi + fputil::multiply_add(-x, p, PI_OVER_TWO.lo); -#else - unsigned idx; - DoubleDouble x_sq = fputil::exact_mult(x, x); - double err = xbits.abs().get_val() * 0x1.0p-51; - // Polynomial approximation: - // p ~ asin(x)/x - DoubleDouble p = asin_eval(x_sq, idx, err); - // asin(x) ~ x * p - DoubleDouble r0 = fputil::exact_mult(x, p.hi); - // acos(x) = pi/2 - asin(x) - // ~ pi/2 - x * p - // = pi/2 - x * (p.hi + p.lo) - double r_hi = fputil::multiply_add(-x, p.hi, PI_OVER_TWO.hi); - // Use Dekker's 2SUM algorithm to compute the lower part. - double r_lo = ((PI_OVER_TWO.hi - r_hi) - r0.hi) - r0.lo; - r_lo = fputil::multiply_add(-x, p.lo, r_lo + PI_OVER_TWO.lo); - - // Ziv's accuracy test. - - double r_upper = r_hi + (r_lo + err); - double r_lower = r_hi + (r_lo - err); - - if (LIBC_LIKELY(r_upper == r_lower)) - return r_upper; - - // Ziv's accuracy test failed, perform 128-bit calculation. - - // Recalculate mod 1/64. - idx = static_cast(fputil::nearest_integer(x_sq.hi * 0x1.0p6)); - - // Get x^2 - idx/64 exactly. When FMA is available, double-double - // multiplication will be correct for all rounding modes. Otherwise we use - // Float128 directly. - Float128 x_f128(x); - -#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE - // u = x^2 - idx/64 - Float128 u_hi( - fputil::multiply_add(static_cast(idx), -0x1.0p-6, x_sq.hi)); - Float128 u = fputil::quick_add(u_hi, Float128(x_sq.lo)); -#else - Float128 x_sq_f128 = fputil::quick_mul(x_f128, x_f128); - Float128 u = fputil::quick_add( - x_sq_f128, Float128(static_cast(idx) * (-0x1.0p-6))); -#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE - - Float128 p_f128 = asin_eval(u, idx); - // Flip the sign of x_f128 to perform subtraction. - x_f128.sign = x_f128.sign.negate(); - Float128 r = - fputil::quick_add(PI_OVER_TWO_F128, fputil::quick_mul(x_f128, p_f128)); - - return static_cast(r); -#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS - } - // |x| >= 0.5 - - double x_abs = xbits.abs().get_val(); - - // Maintaining the sign: - constexpr double SIGN[2] = {1.0, -1.0}; - double x_sign = SIGN[xbits.is_neg()]; - // |x| >= 1 - if (LIBC_UNLIKELY(x_exp >= FPBits::EXP_BIAS)) { - // x = +-1, asin(x) = +- pi/2 - if (x_abs == 1.0) { - // x = 1, acos(x) = 0, - // x = -1, acos(x) = pi - return x == 1.0 ? 0.0 : fputil::multiply_add(-x_sign, PI.hi, PI.lo); - } - // |x| > 1, return NaN. - if (xbits.is_quiet_nan()) - return x; - - // Set domain error for non-NaN input. - if (!xbits.is_nan()) - fputil::set_errno_if_required(EDOM); - - fputil::raise_except_if_required(FE_INVALID); - return FPBits::quiet_nan().get_val(); - } - - // When |x| >= 0.5, we perform range reduction as follow: - // - // When 0.5 <= x < 1, let: - // y = acos(x) - // We will use the double angle formula: - // cos(2y) = 1 - 2 sin^2(y) - // and the complement angle identity: - // x = cos(y) = 1 - 2 sin^2 (y/2) - // So: - // sin(y/2) = sqrt( (1 - x)/2 ) - // And hence: - // y/2 = asin( sqrt( (1 - x)/2 ) ) - // Equivalently: - // acos(x) = y = 2 * asin( sqrt( (1 - x)/2 ) ) - // Let u = (1 - x)/2, then: - // acos(x) = 2 * asin( sqrt(u) ) - // Moreover, since 0.5 <= x < 1: - // 0 < u <= 1/4, and 0 < sqrt(u) <= 0.5, - // And hence we can reuse the same polynomial approximation of asin(x) when - // |x| <= 0.5: - // acos(x) ~ 2 * sqrt(u) * P(u). - // - // When -1 < x <= -0.5, we reduce to the previous case using the formula: - // acos(x) = pi - acos(-x) - // = pi - 2 * asin ( sqrt( (1 + x)/2 ) ) - // ~ pi - 2 * sqrt(u) * P(u), - // where u = (1 - |x|)/2. - - // u = (1 - |x|)/2 - double u = fputil::multiply_add(x_abs, -0.5, 0.5); - // v_hi + v_lo ~ sqrt(u). - // Let: - // h = u - v_hi^2 = (sqrt(u) - v_hi) * (sqrt(u) + v_hi) - // Then: - // sqrt(u) = v_hi + h / (sqrt(u) + v_hi) - // ~ v_hi + h / (2 * v_hi) - // So we can use: - // v_lo = h / (2 * v_hi). - double v_hi = fputil::sqrt(u); - -#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS - constexpr DoubleDouble CONST_TERM[2] = {{0.0, 0.0}, PI}; - DoubleDouble const_term = CONST_TERM[xbits.is_neg()]; - - double p = asin_eval(u); - double scale = x_sign * 2.0 * v_hi; - double r = const_term.hi + fputil::multiply_add(scale, p, const_term.lo); - return r; -#else - -#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE - double h = fputil::multiply_add(v_hi, -v_hi, u); -#else - DoubleDouble v_hi_sq = fputil::exact_mult(v_hi, v_hi); - double h = (u - v_hi_sq.hi) - v_hi_sq.lo; -#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE - - // Scale v_lo and v_hi by 2 from the formula: - // vh = v_hi * 2 - // vl = 2*v_lo = h / v_hi. - double vh = v_hi * 2.0; - double vl = h / v_hi; - - // Polynomial approximation: - // p ~ asin(sqrt(u))/sqrt(u) - unsigned idx; - double err = vh * 0x1.0p-51; - - DoubleDouble p = asin_eval(DoubleDouble{0.0, u}, idx, err); - - // Perform computations in double-double arithmetic: - // asin(x) = pi/2 - (v_hi + v_lo) * (ASIN_COEFFS[idx][0] + p) - DoubleDouble r0 = fputil::quick_mult(DoubleDouble{vl, vh}, p); - - double r_hi, r_lo; - if (xbits.is_pos()) { - r_hi = r0.hi; - r_lo = r0.lo; - } else { - DoubleDouble r = fputil::exact_add(PI.hi, -r0.hi); - r_hi = r.hi; - r_lo = (PI.lo - r0.lo) + r.lo; - } - - // Ziv's accuracy test. - - double r_upper = r_hi + (r_lo + err); - double r_lower = r_hi + (r_lo - err); - - if (LIBC_LIKELY(r_upper == r_lower)) - return r_upper; - - // Ziv's accuracy test failed, we redo the computations in Float128. - // Recalculate mod 1/64. - idx = static_cast(fputil::nearest_integer(u * 0x1.0p6)); - - // After the first step of Newton-Raphson approximating v = sqrt(u), we have - // that: - // sqrt(u) = v_hi + h / (sqrt(u) + v_hi) - // v_lo = h / (2 * v_hi) - // With error: - // sqrt(u) - (v_hi + v_lo) = h * ( 1/(sqrt(u) + v_hi) - 1/(2*v_hi) ) - // = -h^2 / (2*v * (sqrt(u) + v)^2). - // Since: - // (sqrt(u) + v_hi)^2 ~ (2sqrt(u))^2 = 4u, - // we can add another correction term to (v_hi + v_lo) that is: - // v_ll = -h^2 / (2*v_hi * 4u) - // = -v_lo * (h / 4u) - // = -vl * (h / 8u), - // making the errors: - // sqrt(u) - (v_hi + v_lo + v_ll) = O(h^3) - // well beyond 128-bit precision needed. - - // Get the rounding error of vl = 2 * v_lo ~ h / vh - // Get full product of vh * vl -#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE - double vl_lo = fputil::multiply_add(-v_hi, vl, h) / v_hi; -#else - DoubleDouble vh_vl = fputil::exact_mult(v_hi, vl); - double vl_lo = ((h - vh_vl.hi) - vh_vl.lo) / v_hi; -#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE - // vll = 2*v_ll = -vl * (h / (4u)). - double t = h * (-0.25) / u; - double vll = fputil::multiply_add(vl, t, vl_lo); - // m_v = -(v_hi + v_lo + v_ll). - Float128 m_v = fputil::quick_add( - Float128(vh), fputil::quick_add(Float128(vl), Float128(vll))); - m_v.sign = xbits.sign(); - - // Perform computations in Float128: - // acos(x) = (v_hi + v_lo + vll) * P(u) , when 0.5 <= x < 1, - // = pi - (v_hi + v_lo + vll) * P(u) , when -1 < x <= -0.5. - Float128 y_f128(fputil::multiply_add(static_cast(idx), -0x1.0p-6, u)); - - Float128 p_f128 = asin_eval(y_f128, idx); - Float128 r_f128 = fputil::quick_mul(m_v, p_f128); - - if (xbits.is_neg()) - r_f128 = fputil::quick_add(PI_F128, r_f128); - - return static_cast(r_f128); -#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS -} +LLVM_LIBC_FUNCTION(double, acos, (double x)) { return math::acos(x); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/acosf.cpp b/libc/src/math/generic/acosf.cpp index 8dd6de2ce7474..7afc7d661d552 100644 --- a/libc/src/math/generic/acosf.cpp +++ b/libc/src/math/generic/acosf.cpp @@ -7,127 +7,10 @@ //===----------------------------------------------------------------------===// #include "src/math/acosf.h" -#include "src/__support/FPUtil/FEnvImpl.h" -#include "src/__support/FPUtil/FPBits.h" -#include "src/__support/FPUtil/PolyEval.h" -#include "src/__support/FPUtil/except_value_utils.h" -#include "src/__support/FPUtil/multiply_add.h" -#include "src/__support/FPUtil/sqrt.h" -#include "src/__support/macros/config.h" -#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY - -#include "inv_trigf_utils.h" +#include "src/__support/math/acosf.h" namespace LIBC_NAMESPACE_DECL { -#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS -static constexpr size_t N_EXCEPTS = 4; - -// Exceptional values when |x| <= 0.5 -static constexpr fputil::ExceptValues ACOSF_EXCEPTS = {{ - // (inputs, RZ output, RU offset, RD offset, RN offset) - // x = 0x1.110b46p-26, acosf(x) = 0x1.921fb4p0 (RZ) - {0x328885a3, 0x3fc90fda, 1, 0, 1}, - // x = -0x1.110b46p-26, acosf(x) = 0x1.921fb4p0 (RZ) - {0xb28885a3, 0x3fc90fda, 1, 0, 1}, - // x = 0x1.04c444p-12, acosf(x) = 0x1.920f68p0 (RZ) - {0x39826222, 0x3fc907b4, 1, 0, 1}, - // x = -0x1.04c444p-12, acosf(x) = 0x1.923p0 (RZ) - {0xb9826222, 0x3fc91800, 1, 0, 1}, -}}; -#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS - -LLVM_LIBC_FUNCTION(float, acosf, (float x)) { - using FPBits = typename fputil::FPBits; - - FPBits xbits(x); - uint32_t x_uint = xbits.uintval(); - uint32_t x_abs = xbits.uintval() & 0x7fff'ffffU; - uint32_t x_sign = x_uint >> 31; - - // |x| <= 0.5 - if (LIBC_UNLIKELY(x_abs <= 0x3f00'0000U)) { - // |x| < 0x1p-10 - if (LIBC_UNLIKELY(x_abs < 0x3a80'0000U)) { - // When |x| < 2^-10, we use the following approximation: - // acos(x) = pi/2 - asin(x) - // ~ pi/2 - x - x^3 / 6 - -#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS - // Check for exceptional values - if (auto r = ACOSF_EXCEPTS.lookup(x_uint); LIBC_UNLIKELY(r.has_value())) - return r.value(); -#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS - - double xd = static_cast(x); - return static_cast(fputil::multiply_add( - -0x1.5555555555555p-3 * xd, xd * xd, M_MATH_PI_2 - xd)); - } - - // For |x| <= 0.5, we approximate acosf(x) by: - // acos(x) = pi/2 - asin(x) = pi/2 - x * P(x^2) - // Where P(X^2) = Q(X) is a degree-20 minimax even polynomial approximating - // asin(x)/x on [0, 0.5] generated by Sollya with: - // > Q = fpminimax(asin(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20|], - // [|1, D...|], [0, 0.5]); - double xd = static_cast(x); - double xsq = xd * xd; - double x3 = xd * xsq; - double r = asin_eval(xsq); - return static_cast(fputil::multiply_add(-x3, r, M_MATH_PI_2 - xd)); - } - - // |x| >= 1, return 0, 2pi, or NaNs. - if (LIBC_UNLIKELY(x_abs >= 0x3f80'0000U)) { - if (x_abs == 0x3f80'0000U) - return x_sign ? /* x == -1.0f */ fputil::round_result_slightly_down( - 0x1.921fb6p+1f) - : /* x == 1.0f */ 0.0f; - - if (xbits.is_signaling_nan()) { - fputil::raise_except_if_required(FE_INVALID); - return FPBits::quiet_nan().get_val(); - } - - // |x| <= +/-inf - if (x_abs <= 0x7f80'0000U) { - fputil::set_errno_if_required(EDOM); - fputil::raise_except_if_required(FE_INVALID); - } - - return x + FPBits::quiet_nan().get_val(); - } - - // When 0.5 < |x| < 1, we perform range reduction as follow: - // - // Assume further that 0.5 < x <= 1, and let: - // y = acos(x) - // We use the double angle formula: - // x = cos(y) = 1 - 2 sin^2(y/2) - // So: - // sin(y/2) = sqrt( (1 - x)/2 ) - // And hence: - // y = 2 * asin( sqrt( (1 - x)/2 ) ) - // Let u = (1 - x)/2, then - // acos(x) = 2 * asin( sqrt(u) ) - // Moreover, since 0.5 < x <= 1, - // 0 <= u < 1/4, and 0 <= sqrt(u) < 0.5, - // And hence we can reuse the same polynomial approximation of asin(x) when - // |x| <= 0.5: - // acos(x) ~ 2 * sqrt(u) * P(u). - // - // When -1 < x <= -0.5, we use the identity: - // acos(x) = pi - acos(-x) - // which is reduced to the postive case. - - xbits.set_sign(Sign::POS); - double xd = static_cast(xbits.get_val()); - double u = fputil::multiply_add(-0.5, xd, 0.5); - double cv = 2 * fputil::sqrt(u); - - double r3 = asin_eval(u); - double r = fputil::multiply_add(cv * u, r3, cv); - return static_cast(x_sign ? M_MATH_PI - r : r); -} +LLVM_LIBC_FUNCTION(float, acosf, (float x)) { return math::acosf(x); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/acosf16.cpp b/libc/src/math/generic/acosf16.cpp index 202a950fbb5dd..0bf85f84c842c 100644 --- a/libc/src/math/generic/acosf16.cpp +++ b/libc/src/math/generic/acosf16.cpp @@ -8,144 +8,10 @@ //===----------------------------------------------------------------------===// #include "src/math/acosf16.h" -#include "hdr/errno_macros.h" -#include "hdr/fenv_macros.h" -#include "src/__support/FPUtil/FEnvImpl.h" -#include "src/__support/FPUtil/FPBits.h" -#include "src/__support/FPUtil/PolyEval.h" -#include "src/__support/FPUtil/cast.h" -#include "src/__support/FPUtil/except_value_utils.h" -#include "src/__support/FPUtil/multiply_add.h" -#include "src/__support/FPUtil/sqrt.h" -#include "src/__support/macros/optimization.h" +#include "src/__support/math/acosf16.h" namespace LIBC_NAMESPACE_DECL { -// Generated by Sollya using the following command: -// > round(pi/2, SG, RN); -// > round(pi, SG, RN); -static constexpr float PI_OVER_2 = 0x1.921fb6p0f; -static constexpr float PI = 0x1.921fb6p1f; +LLVM_LIBC_FUNCTION(float16, acosf16, (float16 x)) { return math::acosf16(x); } -#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS -static constexpr size_t N_EXCEPTS = 2; - -static constexpr fputil::ExceptValues ACOSF16_EXCEPTS{{ - // (input, RZ output, RU offset, RD offset, RN offset) - {0xacaf, 0x3e93, 1, 0, 0}, - {0xb874, 0x4052, 1, 0, 1}, -}}; -#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS - -LLVM_LIBC_FUNCTION(float16, acosf16, (float16 x)) { - using FPBits = fputil::FPBits; - FPBits xbits(x); - - uint16_t x_u = xbits.uintval(); - uint16_t x_abs = x_u & 0x7fff; - uint16_t x_sign = x_u >> 15; - - // |x| > 0x1p0, |x| > 1, or x is NaN. - if (LIBC_UNLIKELY(x_abs > 0x3c00)) { - // acosf16(NaN) = NaN - if (xbits.is_nan()) { - if (xbits.is_signaling_nan()) { - fputil::raise_except_if_required(FE_INVALID); - return FPBits::quiet_nan().get_val(); - } - - return x; - } - - // 1 < |x| <= +/-inf - fputil::raise_except_if_required(FE_INVALID); - fputil::set_errno_if_required(EDOM); - - return FPBits::quiet_nan().get_val(); - } - - float xf = x; - -#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS - // Handle exceptional values - if (auto r = ACOSF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value())) - return r.value(); -#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS - - // |x| == 0x1p0, x is 1 or -1 - // if x is (-)1, return pi, else - // if x is (+)1, return 0 - if (LIBC_UNLIKELY(x_abs == 0x3c00)) - return fputil::cast(x_sign ? PI : 0.0f); - - float xsq = xf * xf; - - // |x| <= 0x1p-1, |x| <= 0.5 - if (x_abs <= 0x3800) { - // if x is 0, return pi/2 - if (LIBC_UNLIKELY(x_abs == 0)) - return fputil::cast(PI_OVER_2); - - // Note that: acos(x) = pi/2 + asin(-x) = pi/2 - asin(x) - // Degree-6 minimax polynomial of asin(x) generated by Sollya with: - // > P = fpminimax(asin(x)/x, [|0, 2, 4, 6, 8|], [|SG...|], [0, 0.5]); - float interm = - fputil::polyeval(xsq, 0x1.000002p0f, 0x1.554c2ap-3f, 0x1.3541ccp-4f, - 0x1.43b2d6p-5f, 0x1.a0d73ep-5f); - return fputil::cast(fputil::multiply_add(-xf, interm, PI_OVER_2)); - } - - // When |x| > 0.5, assume that 0.5 < |x| <= 1 - // - // Step-by-step range-reduction proof: - // 1: Let y = asin(x), such that, x = sin(y) - // 2: From complimentary angle identity: - // x = sin(y) = cos(pi/2 - y) - // 3: Let z = pi/2 - y, such that x = cos(z) - // 4: From double angle formula; cos(2A) = 1 - 2 * sin^2(A): - // z = 2A, z/2 = A - // cos(z) = 1 - 2 * sin^2(z/2) - // 5: Make sin(z/2) subject of the formula: - // sin(z/2) = sqrt((1 - cos(z))/2) - // 6: Recall [3]; x = cos(z). Therefore: - // sin(z/2) = sqrt((1 - x)/2) - // 7: Let u = (1 - x)/2 - // 8: Therefore: - // asin(sqrt(u)) = z/2 - // 2 * asin(sqrt(u)) = z - // 9: Recall [3]; z = pi/2 - y. Therefore: - // y = pi/2 - z - // y = pi/2 - 2 * asin(sqrt(u)) - // 10: Recall [1], y = asin(x). Therefore: - // asin(x) = pi/2 - 2 * asin(sqrt(u)) - // 11: Recall that: acos(x) = pi/2 + asin(-x) = pi/2 - asin(x) - // Therefore: - // acos(x) = pi/2 - (pi/2 - 2 * asin(sqrt(u))) - // acos(x) = 2 * asin(sqrt(u)) - // - // THE RANGE REDUCTION, HOW? - // 12: Recall [7], u = (1 - x)/2 - // 13: Since 0.5 < x <= 1, therefore: - // 0 <= u <= 0.25 and 0 <= sqrt(u) <= 0.5 - // - // Hence, we can reuse the same [0, 0.5] domain polynomial approximation for - // Step [11] as `sqrt(u)` is in range. - // When -1 < x <= -0.5, the identity: - // acos(x) = pi - acos(-x) - // allows us to compute for the negative x value (lhs) - // with a positive x value instead (rhs). - - float xf_abs = (xf < 0 ? -xf : xf); - float u = fputil::multiply_add(-0.5f, xf_abs, 0.5f); - float sqrt_u = fputil::sqrt(u); - - // Degree-6 minimax polynomial of asin(x) generated by Sollya with: - // > P = fpminimax(asin(x)/x, [|0, 2, 4, 6, 8|], [|SG...|], [0, 0.5]); - float asin_sqrt_u = - sqrt_u * fputil::polyeval(u, 0x1.000002p0f, 0x1.554c2ap-3f, - 0x1.3541ccp-4f, 0x1.43b2d6p-5f, 0x1.a0d73ep-5f); - - return fputil::cast( - x_sign ? fputil::multiply_add(-2.0f, asin_sqrt_u, PI) : 2 * asin_sqrt_u); -} } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/acoshf.cpp b/libc/src/math/generic/acoshf.cpp index c4927fa27a84b..5c04583650e62 100644 --- a/libc/src/math/generic/acoshf.cpp +++ b/libc/src/math/generic/acoshf.cpp @@ -7,73 +7,11 @@ //===----------------------------------------------------------------------===// #include "src/math/acoshf.h" -#include "src/__support/FPUtil/FEnvImpl.h" -#include "src/__support/FPUtil/FPBits.h" -#include "src/__support/FPUtil/PolyEval.h" -#include "src/__support/FPUtil/multiply_add.h" -#include "src/__support/FPUtil/sqrt.h" -#include "src/__support/macros/config.h" -#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY -#include "src/math/generic/common_constants.h" -#include "src/math/generic/explogxf.h" -namespace LIBC_NAMESPACE_DECL { - -LLVM_LIBC_FUNCTION(float, acoshf, (float x)) { - using FPBits_t = typename fputil::FPBits; - FPBits_t xbits(x); - - if (LIBC_UNLIKELY(x <= 1.0f)) { - if (x == 1.0f) - return 0.0f; - // x < 1. - fputil::set_errno_if_required(EDOM); - fputil::raise_except_if_required(FE_INVALID); - return FPBits_t::quiet_nan().get_val(); - } +#include "src/__support/math/acoshf.h" -#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS - uint32_t x_u = xbits.uintval(); - if (LIBC_UNLIKELY(x_u >= 0x4f8ffb03)) { - if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) - return x; - - // Helper functions to set results for exceptional cases. - auto round_result_slightly_down = [](float r) -> float { - volatile float tmp = r; - tmp = tmp - 0x1.0p-25f; - return tmp; - }; - auto round_result_slightly_up = [](float r) -> float { - volatile float tmp = r; - tmp = tmp + 0x1.0p-25f; - return tmp; - }; - - switch (x_u) { - case 0x4f8ffb03: // x = 0x1.1ff606p32f - return round_result_slightly_up(0x1.6fdd34p4f); - case 0x5c569e88: // x = 0x1.ad3d1p57f - return round_result_slightly_up(0x1.45c146p5f); - case 0x5e68984e: // x = 0x1.d1309cp61f - return round_result_slightly_up(0x1.5c9442p5f); - case 0x655890d3: // x = 0x1.b121a6p75f - return round_result_slightly_down(0x1.a9a3f2p5f); - case 0x6eb1a8ec: // x = 0x1.6351d8p94f - return round_result_slightly_down(0x1.08b512p6f); - case 0x7997f30a: // x = 0x1.2fe614p116f - return round_result_slightly_up(0x1.451436p6f); - } - } -#else - if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) - return x; -#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS +namespace LIBC_NAMESPACE_DECL { - double x_d = static_cast(x); - // acosh(x) = log(x + sqrt(x^2 - 1)) - return static_cast(log_eval( - x_d + fputil::sqrt(fputil::multiply_add(x_d, x_d, -1.0)))); -} +LLVM_LIBC_FUNCTION(float, acoshf, (float x)) { return math::acoshf(x); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/acoshf16.cpp b/libc/src/math/generic/acoshf16.cpp index 44783a8749ac2..bb3a91f707080 100644 --- a/libc/src/math/generic/acoshf16.cpp +++ b/libc/src/math/generic/acoshf16.cpp @@ -7,104 +7,10 @@ //===----------------------------------------------------------------------===// #include "src/math/acoshf16.h" -#include "explogxf.h" -#include "hdr/errno_macros.h" -#include "hdr/fenv_macros.h" -#include "src/__support/FPUtil/FEnvImpl.h" -#include "src/__support/FPUtil/FPBits.h" -#include "src/__support/FPUtil/PolyEval.h" -#include "src/__support/FPUtil/cast.h" -#include "src/__support/FPUtil/except_value_utils.h" -#include "src/__support/FPUtil/multiply_add.h" -#include "src/__support/FPUtil/sqrt.h" -#include "src/__support/common.h" -#include "src/__support/macros/config.h" -#include "src/__support/macros/optimization.h" +#include "src/__support/math/acoshf16.h" namespace LIBC_NAMESPACE_DECL { -static constexpr size_t N_EXCEPTS = 2; -static constexpr fputil::ExceptValues ACOSHF16_EXCEPTS{{ - // (input, RZ output, RU offset, RD offset, RN offset) - // x = 0x1.6dcp+1, acoshf16(x) = 0x1.b6p+0 (RZ) - {0x41B7, 0x3ED8, 1, 0, 0}, - // x = 0x1.39p+0, acoshf16(x) = 0x1.4f8p-1 (RZ) - {0x3CE4, 0x393E, 1, 0, 1}, -}}; - -LLVM_LIBC_FUNCTION(float16, acoshf16, (float16 x)) { - using FPBits = fputil::FPBits; - FPBits xbits(x); - uint16_t x_u = xbits.uintval(); - - // Check for NaN input first. - if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) { - if (xbits.is_signaling_nan()) { - fputil::raise_except_if_required(FE_INVALID); - return FPBits::quiet_nan().get_val(); - } - if (xbits.is_neg()) { - fputil::set_errno_if_required(EDOM); - fputil::raise_except_if_required(FE_INVALID); - return FPBits::quiet_nan().get_val(); - } - return x; - } - - // Domain error for inputs less than 1.0. - if (LIBC_UNLIKELY(x <= 1.0f)) { - if (x == 1.0f) - return FPBits::zero().get_val(); - fputil::set_errno_if_required(EDOM); - fputil::raise_except_if_required(FE_INVALID); - return FPBits::quiet_nan().get_val(); - } - - if (auto r = ACOSHF16_EXCEPTS.lookup(xbits.uintval()); - LIBC_UNLIKELY(r.has_value())) - return r.value(); - - float xf = x; - // High-precision polynomial approximation for inputs close to 1.0 - // ([1, 1.25)). - // - // Brief derivation: - // 1. Expand acosh(1 + delta) using Taylor series around delta=0: - // acosh(1 + delta) ≈ sqrt(2 * delta) * [1 - delta/12 + 3*delta^2/160 - // - 5*delta^3/896 + 35*delta^4/18432 + ...] - // 2. Truncate the series to fit accurately for delta in [0, 0.25]. - // 3. Polynomial coefficients (from sollya) used here are: - // P(delta) ≈ 1 - 0x1.555556p-4 * delta + 0x1.333334p-6 * delta^2 - // - 0x1.6db6dcp-8 * delta^3 + 0x1.f1c71cp-10 * delta^4 - // 4. The Sollya commands used to generate these coefficients were: - // > display = hexadecimal; - // > round(1/12, SG, RN); - // > round(3/160, SG, RN); - // > round(5/896, SG, RN); - // > round(35/18432, SG, RN); - // With hexadecimal display mode enabled, the outputs were: - // 0x1.555556p-4 - // 0x1.333334p-6 - // 0x1.6db6dcp-8 - // 0x1.f1c71cp-10 - // 5. The maximum absolute error, estimated using: - // dirtyinfnorm(acosh(1 + x) - sqrt(2*x) * P(x), [0, 0.25]) - // is: - // 0x1.d84281p-22 - if (LIBC_UNLIKELY(x_u < 0x3D00U)) { - float delta = xf - 1.0f; - float sqrt_2_delta = fputil::sqrt(2.0 * delta); - float pe = fputil::polyeval(delta, 0x1p+0f, -0x1.555556p-4f, 0x1.333334p-6f, - -0x1.6db6dcp-8f, 0x1.f1c71cp-10f); - float approx = sqrt_2_delta * pe; - return fputil::cast(approx); - } - - // acosh(x) = log(x + sqrt(x^2 - 1)) - float sqrt_term = fputil::sqrt(fputil::multiply_add(xf, xf, -1.0f)); - float result = static_cast(log_eval(xf + sqrt_term)); - - return fputil::cast(result); -} +LLVM_LIBC_FUNCTION(float16, acoshf16, (float16 x)) { return math::acoshf16(x); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/asin.cpp b/libc/src/math/generic/asin.cpp index ad77683d1f880..d286fceaab6ac 100644 --- a/libc/src/math/generic/asin.cpp +++ b/libc/src/math/generic/asin.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "src/math/asin.h" -#include "asin_utils.h" #include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/PolyEval.h" @@ -18,6 +17,7 @@ #include "src/__support/macros/config.h" #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY #include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA +#include "src/__support/math/asin_utils.h" namespace LIBC_NAMESPACE_DECL { @@ -25,6 +25,7 @@ using DoubleDouble = fputil::DoubleDouble; using Float128 = fputil::DyadicFloat<128>; LLVM_LIBC_FUNCTION(double, asin, (double x)) { + using namespace asin_internal; using FPBits = fputil::FPBits; FPBits xbits(x); diff --git a/libc/src/math/generic/asinf.cpp b/libc/src/math/generic/asinf.cpp index 12383bf6dacae..77d6de910962c 100644 --- a/libc/src/math/generic/asinf.cpp +++ b/libc/src/math/generic/asinf.cpp @@ -17,7 +17,7 @@ #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY #include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA -#include "inv_trigf_utils.h" +#include "src/__support/math/inv_trigf_utils.h" namespace LIBC_NAMESPACE_DECL { @@ -44,6 +44,7 @@ static constexpr fputil::ExceptValues ASINF_EXCEPTS_HI = {{ #endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS LLVM_LIBC_FUNCTION(float, asinf, (float x)) { + using namespace inv_trigf_utils_internal; using FPBits = typename fputil::FPBits; FPBits xbits(x); diff --git a/libc/src/math/generic/asinhf.cpp b/libc/src/math/generic/asinhf.cpp index 0bb7065eb1cfe..3aed3bc2c9cde 100644 --- a/libc/src/math/generic/asinhf.cpp +++ b/libc/src/math/generic/asinhf.cpp @@ -19,6 +19,7 @@ namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(float, asinhf, (float x)) { + using namespace acoshf_internal; using FPBits_t = typename fputil::FPBits; FPBits_t xbits(x); uint32_t x_u = xbits.uintval(); diff --git a/libc/src/math/generic/asinhf16.cpp b/libc/src/math/generic/asinhf16.cpp index 78786320b5f71..0a0b471d87ecc 100644 --- a/libc/src/math/generic/asinhf16.cpp +++ b/libc/src/math/generic/asinhf16.cpp @@ -49,6 +49,7 @@ static constexpr fputil::ExceptValues ASINHF16_EXCEPTS{{ #endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS LLVM_LIBC_FUNCTION(float16, asinhf16, (float16 x)) { + using namespace acoshf_internal; using FPBits = fputil::FPBits; FPBits xbits(x); diff --git a/libc/src/math/generic/atan2f.cpp b/libc/src/math/generic/atan2f.cpp index c04b0eb1cc589..32b977f45d7e7 100644 --- a/libc/src/math/generic/atan2f.cpp +++ b/libc/src/math/generic/atan2f.cpp @@ -8,7 +8,6 @@ #include "src/math/atan2f.h" #include "hdr/fenv_macros.h" -#include "inv_trigf_utils.h" #include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/PolyEval.h" @@ -18,6 +17,7 @@ #include "src/__support/FPUtil/rounding_mode.h" #include "src/__support/macros/config.h" #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY +#include "src/__support/math/inv_trigf_utils.h" #if defined(LIBC_MATH_HAS_SKIP_ACCURATE_PASS) && \ defined(LIBC_MATH_HAS_INTERMEDIATE_COMP_IN_FLOAT) @@ -236,6 +236,7 @@ float atan2f_double_double(double num_d, double den_d, double q_d, int idx, // which is about rounding errors of double-double (2^-104). LLVM_LIBC_FUNCTION(float, atan2f, (float y, float x)) { + using namespace inv_trigf_utils_internal; using FPBits = typename fputil::FPBits; constexpr double IS_NEG[2] = {1.0, -1.0}; constexpr double PI = 0x1.921fb54442d18p1; diff --git a/libc/src/math/generic/atanf.cpp b/libc/src/math/generic/atanf.cpp index 46196dbe4162c..22f962ef4cce4 100644 --- a/libc/src/math/generic/atanf.cpp +++ b/libc/src/math/generic/atanf.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "src/math/atanf.h" -#include "inv_trigf_utils.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/PolyEval.h" #include "src/__support/FPUtil/except_value_utils.h" @@ -16,10 +15,12 @@ #include "src/__support/FPUtil/rounding_mode.h" #include "src/__support/macros/config.h" #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY +#include "src/__support/math/inv_trigf_utils.h" namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(float, atanf, (float x)) { + using namespace inv_trigf_utils_internal; using FPBits = typename fputil::FPBits; constexpr double FINAL_SIGN[2] = {1.0, -1.0}; diff --git a/libc/src/math/generic/atanhf.cpp b/libc/src/math/generic/atanhf.cpp index 2149314d2f676..602a8f042f783 100644 --- a/libc/src/math/generic/atanhf.cpp +++ b/libc/src/math/generic/atanhf.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "src/math/atanhf.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/macros/config.h" #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY @@ -15,6 +16,7 @@ namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(float, atanhf, (float x)) { + using namespace acoshf_internal; using FPBits = typename fputil::FPBits; FPBits xbits(x); diff --git a/libc/src/math/generic/common_constants.cpp b/libc/src/math/generic/common_constants.cpp index 4dcf84d00ad50..42e3ff0deb348 100644 --- a/libc/src/math/generic/common_constants.cpp +++ b/libc/src/math/generic/common_constants.cpp @@ -51,52 +51,6 @@ const float ONE_OVER_F_FLOAT[128] = { 0x1.08421p-1f, 0x1.07326p-1f, 0x1.0624dep-1f, 0x1.05198p-1f, 0x1.041042p-1f, 0x1.03091cp-1f, 0x1.020408p-1f, 0x1.010102p-1f}; -// Lookup table for (1/f) where f = 1 + n*2^(-7), n = 0..127. -const double ONE_OVER_F[128] = { - 0x1.0000000000000p+0, 0x1.fc07f01fc07f0p-1, 0x1.f81f81f81f820p-1, - 0x1.f44659e4a4271p-1, 0x1.f07c1f07c1f08p-1, 0x1.ecc07b301ecc0p-1, - 0x1.e9131abf0b767p-1, 0x1.e573ac901e574p-1, 0x1.e1e1e1e1e1e1ep-1, - 0x1.de5d6e3f8868ap-1, 0x1.dae6076b981dbp-1, 0x1.d77b654b82c34p-1, - 0x1.d41d41d41d41dp-1, 0x1.d0cb58f6ec074p-1, 0x1.cd85689039b0bp-1, - 0x1.ca4b3055ee191p-1, 0x1.c71c71c71c71cp-1, 0x1.c3f8f01c3f8f0p-1, - 0x1.c0e070381c0e0p-1, 0x1.bdd2b899406f7p-1, 0x1.bacf914c1bad0p-1, - 0x1.b7d6c3dda338bp-1, 0x1.b4e81b4e81b4fp-1, 0x1.b2036406c80d9p-1, - 0x1.af286bca1af28p-1, 0x1.ac5701ac5701bp-1, 0x1.a98ef606a63bep-1, - 0x1.a6d01a6d01a6dp-1, 0x1.a41a41a41a41ap-1, 0x1.a16d3f97a4b02p-1, - 0x1.9ec8e951033d9p-1, 0x1.9c2d14ee4a102p-1, 0x1.999999999999ap-1, - 0x1.970e4f80cb872p-1, 0x1.948b0fcd6e9e0p-1, 0x1.920fb49d0e229p-1, - 0x1.8f9c18f9c18fap-1, 0x1.8d3018d3018d3p-1, 0x1.8acb90f6bf3aap-1, - 0x1.886e5f0abb04ap-1, 0x1.8618618618618p-1, 0x1.83c977ab2beddp-1, - 0x1.8181818181818p-1, 0x1.7f405fd017f40p-1, 0x1.7d05f417d05f4p-1, - 0x1.7ad2208e0ecc3p-1, 0x1.78a4c8178a4c8p-1, 0x1.767dce434a9b1p-1, - 0x1.745d1745d1746p-1, 0x1.724287f46debcp-1, 0x1.702e05c0b8170p-1, - 0x1.6e1f76b4337c7p-1, 0x1.6c16c16c16c17p-1, 0x1.6a13cd1537290p-1, - 0x1.6816816816817p-1, 0x1.661ec6a5122f9p-1, 0x1.642c8590b2164p-1, - 0x1.623fa77016240p-1, 0x1.6058160581606p-1, 0x1.5e75bb8d015e7p-1, - 0x1.5c9882b931057p-1, 0x1.5ac056b015ac0p-1, 0x1.58ed2308158edp-1, - 0x1.571ed3c506b3ap-1, 0x1.5555555555555p-1, 0x1.5390948f40febp-1, - 0x1.51d07eae2f815p-1, 0x1.5015015015015p-1, 0x1.4e5e0a72f0539p-1, - 0x1.4cab88725af6ep-1, 0x1.4afd6a052bf5bp-1, 0x1.49539e3b2d067p-1, - 0x1.47ae147ae147bp-1, 0x1.460cbc7f5cf9ap-1, 0x1.446f86562d9fbp-1, - 0x1.42d6625d51f87p-1, 0x1.4141414141414p-1, 0x1.3fb013fb013fbp-1, - 0x1.3e22cbce4a902p-1, 0x1.3c995a47babe7p-1, 0x1.3b13b13b13b14p-1, - 0x1.3991c2c187f63p-1, 0x1.3813813813814p-1, 0x1.3698df3de0748p-1, - 0x1.3521cfb2b78c1p-1, 0x1.33ae45b57bcb2p-1, 0x1.323e34a2b10bfp-1, - 0x1.30d190130d190p-1, 0x1.2f684bda12f68p-1, 0x1.2e025c04b8097p-1, - 0x1.2c9fb4d812ca0p-1, 0x1.2b404ad012b40p-1, 0x1.29e4129e4129ep-1, - 0x1.288b01288b013p-1, 0x1.27350b8812735p-1, 0x1.25e22708092f1p-1, - 0x1.2492492492492p-1, 0x1.23456789abcdfp-1, 0x1.21fb78121fb78p-1, - 0x1.20b470c67c0d9p-1, 0x1.1f7047dc11f70p-1, 0x1.1e2ef3b3fb874p-1, - 0x1.1cf06ada2811dp-1, 0x1.1bb4a4046ed29p-1, 0x1.1a7b9611a7b96p-1, - 0x1.19453808ca29cp-1, 0x1.1811811811812p-1, 0x1.16e0689427379p-1, - 0x1.15b1e5f75270dp-1, 0x1.1485f0e0acd3bp-1, 0x1.135c81135c811p-1, - 0x1.12358e75d3033p-1, 0x1.1111111111111p-1, 0x1.0fef010fef011p-1, - 0x1.0ecf56be69c90p-1, 0x1.0db20a88f4696p-1, 0x1.0c9714fbcda3bp-1, - 0x1.0b7e6ec259dc8p-1, 0x1.0a6810a6810a7p-1, 0x1.0953f39010954p-1, - 0x1.0842108421084p-1, 0x1.073260a47f7c6p-1, 0x1.0624dd2f1a9fcp-1, - 0x1.05197f7d73404p-1, 0x1.0410410410410p-1, 0x1.03091b51f5e1ap-1, - 0x1.0204081020408p-1, 0x1.0101010101010p-1}; - // Lookup table for log(f) = log(1 + n*2^(-7)) where n = 0..127, // computed and stored as float precision constants. // Generated by Sollya with the following commands: @@ -136,52 +90,6 @@ const float LOG_F_FLOAT[128] = { 0x1.52a2d2p-1f, 0x1.54b246p-1f, 0x1.56bf9ep-1f, 0x1.58cadcp-1f, 0x1.5ad404p-1f, 0x1.5cdb1ep-1f, 0x1.5ee02ap-1f, 0x1.60e33p-1f}; -// Lookup table for log(f) = log(1 + n*2^(-7)) where n = 0..127. -const double LOG_F[128] = { - 0x0.0000000000000p+0, 0x1.fe02a6b106788p-8, 0x1.fc0a8b0fc03e3p-7, - 0x1.7b91b07d5b11ap-6, 0x1.f829b0e783300p-6, 0x1.39e87b9febd5fp-5, - 0x1.77458f632dcfcp-5, 0x1.b42dd711971bep-5, 0x1.f0a30c01162a6p-5, - 0x1.16536eea37ae0p-4, 0x1.341d7961bd1d0p-4, 0x1.51b073f06183fp-4, - 0x1.6f0d28ae56b4bp-4, 0x1.8c345d6319b20p-4, 0x1.a926d3a4ad563p-4, - 0x1.c5e548f5bc743p-4, 0x1.e27076e2af2e5p-4, 0x1.fec9131dbeabap-4, - 0x1.0d77e7cd08e59p-3, 0x1.1b72ad52f67a0p-3, 0x1.29552f81ff523p-3, - 0x1.371fc201e8f74p-3, 0x1.44d2b6ccb7d1ep-3, 0x1.526e5e3a1b437p-3, - 0x1.5ff3070a793d3p-3, 0x1.6d60fe719d21cp-3, 0x1.7ab890210d909p-3, - 0x1.87fa06520c910p-3, 0x1.9525a9cf456b4p-3, 0x1.a23bc1fe2b563p-3, - 0x1.af3c94e80bff2p-3, 0x1.bc286742d8cd6p-3, 0x1.c8ff7c79a9a21p-3, - 0x1.d5c216b4fbb91p-3, 0x1.e27076e2af2e5p-3, 0x1.ef0adcbdc5936p-3, - 0x1.fb9186d5e3e2ap-3, 0x1.0402594b4d040p-2, 0x1.0a324e27390e3p-2, - 0x1.1058bf9ae4ad5p-2, 0x1.1675cababa60ep-2, 0x1.1c898c16999fap-2, - 0x1.22941fbcf7965p-2, 0x1.2895a13de86a3p-2, 0x1.2e8e2bae11d30p-2, - 0x1.347dd9a987d54p-2, 0x1.3a64c556945e9p-2, 0x1.404308686a7e3p-2, - 0x1.4618bc21c5ec2p-2, 0x1.4be5f957778a0p-2, 0x1.51aad872df82dp-2, - 0x1.5767717455a6cp-2, 0x1.5d1bdbf5809cap-2, 0x1.62c82f2b9c795p-2, - 0x1.686c81e9b14aep-2, 0x1.6e08eaa2ba1e3p-2, 0x1.739d7f6bbd006p-2, - 0x1.792a55fdd47a2p-2, 0x1.7eaf83b82afc3p-2, 0x1.842d1da1e8b17p-2, - 0x1.89a3386c1425ap-2, 0x1.8f11e873662c7p-2, 0x1.947941c2116fap-2, - 0x1.99d958117e08ap-2, 0x1.9f323ecbf984bp-2, 0x1.a484090e5bb0ap-2, - 0x1.a9cec9a9a0849p-2, 0x1.af1293247786bp-2, 0x1.b44f77bcc8f62p-2, - 0x1.b9858969310fbp-2, 0x1.beb4d9da71b7bp-2, 0x1.c3dd7a7cdad4dp-2, - 0x1.c8ff7c79a9a21p-2, 0x1.ce1af0b85f3ebp-2, 0x1.d32fe7e00ebd5p-2, - 0x1.d83e7258a2f3ep-2, 0x1.dd46a04c1c4a0p-2, 0x1.e24881a7c6c26p-2, - 0x1.e744261d68787p-2, 0x1.ec399d2468cc0p-2, 0x1.f128f5faf06ecp-2, - 0x1.f6123fa7028acp-2, 0x1.faf588f78f31ep-2, 0x1.ffd2e0857f498p-2, - 0x1.02552a5a5d0fep-1, 0x1.04bdf9da926d2p-1, 0x1.0723e5c1cdf40p-1, - 0x1.0986f4f573520p-1, 0x1.0be72e4252a82p-1, 0x1.0e44985d1cc8bp-1, - 0x1.109f39e2d4c96p-1, 0x1.12f719593efbcp-1, 0x1.154c3d2f4d5e9p-1, - 0x1.179eabbd899a0p-1, 0x1.19ee6b467c96ep-1, 0x1.1c3b81f713c24p-1, - 0x1.1e85f5e7040d0p-1, 0x1.20cdcd192ab6dp-1, 0x1.23130d7bebf42p-1, - 0x1.2555bce98f7cbp-1, 0x1.2795e1289b11ap-1, 0x1.29d37fec2b08ap-1, - 0x1.2c0e9ed448e8bp-1, 0x1.2e47436e40268p-1, 0x1.307d7334f10bep-1, - 0x1.32b1339121d71p-1, 0x1.34e289d9ce1d3p-1, 0x1.37117b54747b5p-1, - 0x1.393e0d3562a19p-1, 0x1.3b68449fffc22p-1, 0x1.3d9026a7156fap-1, - 0x1.3fb5b84d16f42p-1, 0x1.41d8fe84672aep-1, 0x1.43f9fe2f9ce67p-1, - 0x1.4618bc21c5ec2p-1, 0x1.48353d1ea88dfp-1, 0x1.4a4f85db03ebbp-1, - 0x1.4c679afccee39p-1, 0x1.4e7d811b75bb0p-1, 0x1.50913cc01686bp-1, - 0x1.52a2d265bc5aap-1, 0x1.54b2467999497p-1, 0x1.56bf9d5b3f399p-1, - 0x1.58cadb5cd7989p-1, 0x1.5ad404c359f2cp-1, 0x1.5cdb1dc6c1764p-1, - 0x1.5ee02a9241675p-1, 0x1.60e32f44788d8p-1}; - // Range reduction constants for logarithms. // r(0) = 1, r(127) = 0.5 // r(k) = 2^-8 * ceil(2^8 * (1 - 2^-8) / (1 + k*2^-7)) diff --git a/libc/src/math/generic/common_constants.h b/libc/src/math/generic/common_constants.h index 291816a7889ad..72b1d564ca472 100644 --- a/libc/src/math/generic/common_constants.h +++ b/libc/src/math/generic/common_constants.h @@ -11,6 +11,7 @@ #include "src/__support/FPUtil/triple_double.h" #include "src/__support/macros/config.h" +#include "src/__support/math/acosh_float_constants.h" #include "src/__support/math/exp_constants.h" #include "src/__support/number_pair.h" @@ -20,16 +21,10 @@ namespace LIBC_NAMESPACE_DECL { // computed and stored as float precision constants. extern const float ONE_OVER_F_FLOAT[128]; -// Lookup table for (1/f) where f = 1 + n*2^(-7), n = 0..127. -extern const double ONE_OVER_F[128]; - // Lookup table for log(f) = log(1 + n*2^(-7)) where n = 0..127, // computed and stored as float precision constants. extern const float LOG_F_FLOAT[128]; -// Lookup table for log(f) = log(1 + n*2^(-7)) where n = 0..127. -extern const double LOG_F[128]; - // Lookup table for range reduction constants r for logarithms. extern const float R[128]; diff --git a/libc/src/math/generic/coshf.cpp b/libc/src/math/generic/coshf.cpp index c869f7d9dec5f..9f87564d524a6 100644 --- a/libc/src/math/generic/coshf.cpp +++ b/libc/src/math/generic/coshf.cpp @@ -7,8 +7,8 @@ //===----------------------------------------------------------------------===// #include "src/math/coshf.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" -#include "src/__support/FPUtil/multiply_add.h" #include "src/__support/FPUtil/rounding_mode.h" #include "src/__support/macros/config.h" #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY diff --git a/libc/src/math/generic/erff.cpp b/libc/src/math/generic/erff.cpp index 44607a52a2e57..003b3465ac597 100644 --- a/libc/src/math/generic/erff.cpp +++ b/libc/src/math/generic/erff.cpp @@ -7,180 +7,10 @@ //===----------------------------------------------------------------------===// #include "src/math/erff.h" -#include "src/__support/FPUtil/FPBits.h" -#include "src/__support/FPUtil/PolyEval.h" -#include "src/__support/FPUtil/except_value_utils.h" -#include "src/__support/FPUtil/multiply_add.h" -#include "src/__support/common.h" -#include "src/__support/macros/config.h" -#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY +#include "src/__support/math/erff.h" namespace LIBC_NAMESPACE_DECL { -// Polynomials approximating erf(x)/x on ( k/8, (k + 1)/8 ) generated by Sollya -// with: -// > P = fpminimax(erf(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14|], [|D...|], -// [k/8, (k + 1)/8]); -// for k = 0..31. -constexpr double COEFFS[32][8] = { - {0x1.20dd750429b6dp0, -0x1.812746b037753p-2, 0x1.ce2f219e8596ap-4, - -0x1.b82cdacb78fdap-6, 0x1.56479297dfda5p-8, -0x1.8b3ac5455ef02p-11, - -0x1.126fcac367e3bp-8, 0x1.2d0bdb3ba4984p-4}, - {0x1.20dd750429b6dp0, -0x1.812746b0379a8p-2, 0x1.ce2f21a03cf2ap-4, - -0x1.b82ce30de083ep-6, 0x1.565bcad3eb60fp-8, -0x1.c02c66f659256p-11, - 0x1.f92f673385229p-14, -0x1.def402648ae9p-17}, - {0x1.20dd750429b34p0, -0x1.812746b032dcep-2, 0x1.ce2f219d84aaep-4, - -0x1.b82ce22dcf139p-6, 0x1.565b9efcd4af1p-8, -0x1.c021f1af414bcp-11, - 0x1.f7c6d177eff82p-14, -0x1.c9e4410dcf865p-17}, - {0x1.20dd750426eabp0, -0x1.812746ae592c7p-2, 0x1.ce2f211525f14p-4, - -0x1.b82ccc125e63fp-6, 0x1.56596f261cfd3p-8, -0x1.bfde1ff8eeecfp-11, - 0x1.f31a9d15dc5d8p-14, -0x1.a5a4362844b3cp-17}, - {0x1.20dd75039c705p0, -0x1.812746777e74dp-2, 0x1.ce2f17af98a1bp-4, - -0x1.b82be4b817cbep-6, 0x1.564bec2e2962ep-8, -0x1.bee86f9da3558p-11, - 0x1.e9443689dc0ccp-14, -0x1.79c0f230805d8p-17}, - {0x1.20dd74f811211p0, -0x1.81274371a3e8fp-2, 0x1.ce2ec038262e5p-4, - -0x1.b8265b82c5e1fp-6, 0x1.5615a2e239267p-8, -0x1.bc63ae023dcebp-11, - 0x1.d87c2102f7e06p-14, -0x1.49584bea41d62p-17}, - {0x1.20dd746d063e3p0, -0x1.812729a8a950fp-2, 0x1.ce2cb0a2df232p-4, - -0x1.b80eca1f51278p-6, 0x1.5572e26c46815p-8, -0x1.b715e5638b65ep-11, - 0x1.bfbb195484968p-14, -0x1.177a565c15c52p-17}, - {0x1.20dd701b44486p0, -0x1.812691145f237p-2, 0x1.ce23a06b8cfd9p-4, - -0x1.b7c1dc7245288p-6, 0x1.53e92f7f397ddp-8, -0x1.ad97cc4acf0b2p-11, - 0x1.9f028b2b09b71p-14, -0x1.cdc4da08da8c1p-18}, - {0x1.20dd5715ac332p0, -0x1.8123e680bd0ebp-2, 0x1.ce0457aded691p-4, - -0x1.b6f52d52bed4p-6, 0x1.50c291b84414cp-8, -0x1.9ea246b1ad4a9p-11, - 0x1.77654674e0cap-14, -0x1.737c11a1bcebbp-18}, - {0x1.20dce6593e114p0, -0x1.811a59c02eadcp-2, 0x1.cdab53c7cd7d5p-4, - -0x1.b526d2e321eedp-6, 0x1.4b1d32cd8b994p-8, -0x1.8963143ec0a1ep-11, - 0x1.4ad5700e4db91p-14, -0x1.231e100e43ef2p-18}, - {0x1.20db48bfd5a62p0, -0x1.80fdd84f9e308p-2, 0x1.ccd340d462983p-4, - -0x1.b196a2928768p-6, 0x1.4210c2c13a0f7p-8, -0x1.6dbdfb4ff71aep-11, - 0x1.1bca2d17fbd71p-14, -0x1.bca36f90c7cf5p-19}, - {0x1.20d64b2f8f508p0, -0x1.80b4d4f19fa8bp-2, 0x1.cb088197262e3p-4, - -0x1.ab51fd02e5b99p-6, 0x1.34e1e5e81a632p-8, -0x1.4c66377b502cep-11, - 0x1.d9ad25066213cp-15, -0x1.4b0df7dd0cfa1p-19}, - {0x1.20c8fc1243576p0, -0x1.8010cb2009e27p-2, 0x1.c7a47e9299315p-4, - -0x1.a155be5683654p-6, 0x1.233502694997bp-8, -0x1.26c94b7d813p-11, - 0x1.8094f1de25fb9p-15, -0x1.e0e3d776c6eefp-20}, - {0x1.20a9bd1611bc1p0, -0x1.7ec7fbce83f9p-2, 0x1.c1d757d7317b7p-4, - -0x1.92c160cd589fp-6, 0x1.0d307269cc5c2p-8, -0x1.fda5b0d2d1879p-12, - 0x1.2fdd7b3b14a7fp-15, -0x1.54eed4a26af5ap-20}, - {0x1.20682834f943dp0, -0x1.7c73f747bf5a9p-2, 0x1.b8c2db4a9ffd1p-4, - -0x1.7f0e4ffe989ecp-6, 0x1.e7061eae4166ep-9, -0x1.ad36e873fff2dp-12, - 0x1.d39222396128ep-16, -0x1.d83dacec5ea6bp-21}, - {0x1.1feb8d12676d7p0, -0x1.7898347284afep-2, 0x1.aba3466b34451p-4, - -0x1.663adc573e2f9p-6, 0x1.ae99fb17c3e08p-9, -0x1.602f950ad5535p-12, - 0x1.5e9717490609dp-16, -0x1.3fca107bbc8d5p-21}, - {0x1.1f12fe3c536fap0, -0x1.72b1d1f22e6d3p-2, 0x1.99fc0eed4a896p-4, - -0x1.48db0a87bd8c6p-6, 0x1.73e368895aa61p-9, -0x1.19b35d5301fc8p-12, - 0x1.007987e4bb033p-16, -0x1.a7edcd4c2dc7p-22}, - {0x1.1db7b0df84d5dp0, -0x1.6a4e4a41cde02p-2, 0x1.83bbded16455dp-4, - -0x1.2809b3b36977ep-6, 0x1.39c08bab44679p-9, -0x1.b7b45a70ed119p-13, - 0x1.6e99b36410e7bp-17, -0x1.13619bb7ebc0cp-22}, - {0x1.1bb1c85c4a527p0, -0x1.5f23b99a249a3p-2, 0x1.694c91fa0d12cp-4, - -0x1.053e1ce11c72dp-6, 0x1.02bf72c50ea78p-9, -0x1.4f478fb56cb02p-13, - 0x1.005f80ecbe213p-17, -0x1.5f2446bde7f5bp-23}, - {0x1.18dec3bd51f9dp0, -0x1.5123f58346186p-2, 0x1.4b8a1ca536ab4p-4, - -0x1.c4243015cc723p-7, 0x1.a1a8a01d351efp-10, -0x1.f466b34f1d86bp-14, - 0x1.5f835eea0bf6ap-18, -0x1.b83165b939234p-24}, - {0x1.152804c3369f4p0, -0x1.4084cd4afd4bcp-2, 0x1.2ba2e836e47aap-4, - -0x1.800f2dfc6904bp-7, 0x1.4a6daf0669c59p-10, -0x1.6e326ab872317p-14, - 0x1.d9761a6a755a5p-19, -0x1.0fca33f9dd4b5p-24}, - {0x1.1087ad68356aap0, -0x1.2dbb044707459p-2, 0x1.0aea8ceaa0384p-4, - -0x1.40b516d52b3d2p-7, 0x1.00c9e05f01d22p-10, -0x1.076afb0dc0ff7p-14, - 0x1.39fadec400657p-19, -0x1.4b5761352e7e3p-25}, - {0x1.0b0a7a8ba4a22p0, -0x1.196990d22d4a1p-2, 0x1.d5551e6ac0c4dp-5, - -0x1.07cce1770bd1ap-7, 0x1.890347b8848bfp-11, -0x1.757ec96750b6ap-15, - 0x1.9b258a1e06bcep-20, -0x1.8fc6d22da7572p-26}, - {0x1.04ce2be70fb47p0, -0x1.0449e4b0b9cacp-2, 0x1.97f7424f4b0e7p-5, - -0x1.ac825439c42f4p-8, 0x1.28f5f65426dfbp-11, -0x1.05b699a90f90fp-15, - 0x1.0a888eecf4593p-20, -0x1.deace2b32bb31p-27}, - {0x1.fbf9fb0e11cc8p-1, -0x1.de2640856545ap-3, 0x1.5f5b1f47f851p-5, - -0x1.588bc71eb41b9p-8, 0x1.bc6a0a772f56dp-12, -0x1.6b9fad1f1657ap-16, - 0x1.573204ba66504p-21, -0x1.1d38065c94e44p-27}, - {0x1.ed8f18c99e031p-1, -0x1.b4cb6acd903b4p-3, 0x1.2c7f3dddd6fc1p-5, - -0x1.13052067df4ep-8, 0x1.4a5027444082fp-12, -0x1.f672bab0e2554p-17, - 0x1.b83c756348cc9p-22, -0x1.534f1a1079499p-28}, - {0x1.debd33044166dp-1, -0x1.8d7cd9053f7d8p-3, 0x1.ff9957fb3d6e7p-6, - -0x1.b50be55de0f36p-9, 0x1.e92c8ec53a628p-13, -0x1.5a4b88d508007p-17, - 0x1.1a27737559e26p-22, -0x1.942ae62cb2c14p-29}, - {0x1.cfdbf0386f3bdp-1, -0x1.68e33d93b0dc4p-3, 0x1.b2683d58f53dep-6, - -0x1.5a9174e70d26fp-9, 0x1.69ddd326d49cdp-13, -0x1.dd8f397a8219cp-18, - 0x1.6a755016ad4ddp-23, -0x1.e366e0139187dp-30}, - {0x1.c132adb8d7464p-1, -0x1.475a899f61b46p-3, 0x1.70a431397a77cp-6, - -0x1.12e3d35beeee2p-9, 0x1.0c16b05738333p-13, -0x1.4a47f873e144ep-18, - 0x1.d3d494c698c02p-24, -0x1.2302c59547fe5p-30}, - {0x1.b2f5fd05555e7p-1, -0x1.28feefbe03ec7p-3, 0x1.3923acbb3a676p-6, - -0x1.b4ff793cd6358p-10, 0x1.8ea0eb8c913bcp-14, -0x1.cb31ec2baceb1p-19, - 0x1.30011e7e80c04p-24, -0x1.617710635cb1dp-31}, - {0x1.a54853cd9593ep-1, -0x1.0dbdbaea4dc8ep-3, 0x1.0a93e2c20a0fdp-6, - -0x1.5c969ff401ea8p-10, 0x1.29e0cc64fe627p-14, -0x1.4160d8e9d3c2ap-19, - 0x1.8e7b67594624ap-25, -0x1.b1cf2c975b09bp-32}, - {0x1.983ceece09ff8p-1, -0x1.eacc78f7a2dp-4, 0x1.c74418410655fp-7, - -0x1.1756a050e441ep-10, 0x1.bff3650f7f548p-15, -0x1.c56c0217d3adap-20, - 0x1.07b4918d0b489p-25, -0x1.0d4be8c1c50f8p-32}, -}; - -LLVM_LIBC_FUNCTION(float, erff, (float x)) { - using FPBits = typename fputil::FPBits; - FPBits xbits(x); - - uint32_t x_u = xbits.uintval(); - uint32_t x_abs = x_u & 0x7fff'ffffU; - - if (LIBC_UNLIKELY(x_abs >= 0x4080'0000U)) { - const float ONE[2] = {1.0f, -1.0f}; - const float SMALL[2] = {-0x1.0p-25f, 0x1.0p-25f}; - - int sign = xbits.is_neg() ? 1 : 0; - - if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) { - if (xbits.is_signaling_nan()) { - fputil::raise_except_if_required(FE_INVALID); - return FPBits::quiet_nan().get_val(); - } - return (x_abs > 0x7f80'0000) ? x : ONE[sign]; - } - - return ONE[sign] + SMALL[sign]; - } - -#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS - // Exceptional mask = common 0 bits of 2 exceptional values. - constexpr uint32_t EXCEPT_MASK = 0x809a'6184U; - - if (LIBC_UNLIKELY((x_abs & EXCEPT_MASK) == 0)) { - // Exceptional values - if (LIBC_UNLIKELY(x_abs == 0x3f65'9229U)) // |x| = 0x1.cb2452p-1f - return x < 0.0f ? fputil::round_result_slightly_down(-0x1.972ea8p-1f) - : fputil::round_result_slightly_up(0x1.972ea8p-1f); - if (LIBC_UNLIKELY(x_abs == 0x4004'1e6aU)) // |x| = 0x1.083cd4p+1f - return x < 0.0f ? fputil::round_result_slightly_down(-0x1.fe3462p-1f) - : fputil::round_result_slightly_up(0x1.fe3462p-1f); - if (x_abs == 0U) - return x; - } -#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS - - // Polynomial approximation: - // erf(x) ~ x * (c0 + c1 * x^2 + c2 * x^4 + ... + c7 * x^14) - double xd = static_cast(x); - double xsq = xd * xd; - - const uint32_t EIGHT = 3 << FPBits::FRACTION_LEN; - int idx = static_cast(FPBits(x_abs + EIGHT).get_val()); - - double x4 = xsq * xsq; - double c0 = fputil::multiply_add(xsq, COEFFS[idx][1], COEFFS[idx][0]); - double c1 = fputil::multiply_add(xsq, COEFFS[idx][3], COEFFS[idx][2]); - double c2 = fputil::multiply_add(xsq, COEFFS[idx][5], COEFFS[idx][4]); - double c3 = fputil::multiply_add(xsq, COEFFS[idx][7], COEFFS[idx][6]); - - double x8 = x4 * x4; - double p0 = fputil::multiply_add(x4, c1, c0); - double p1 = fputil::multiply_add(x4, c3, c2); - - return static_cast(xd * fputil::multiply_add(x8, p1, p0)); -} +LLVM_LIBC_FUNCTION(float, erff, (float x)) { return math::erff(x); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/exp10.cpp b/libc/src/math/generic/exp10.cpp index c464979b092c3..5c36d28c166ae 100644 --- a/libc/src/math/generic/exp10.cpp +++ b/libc/src/math/generic/exp10.cpp @@ -7,491 +7,10 @@ //===----------------------------------------------------------------------===// #include "src/math/exp10.h" -#include "common_constants.h" // Lookup tables EXP2_MID1 and EXP_M2. -#include "explogxf.h" // ziv_test_denorm. -#include "src/__support/CPP/bit.h" -#include "src/__support/CPP/optional.h" -#include "src/__support/FPUtil/FEnvImpl.h" -#include "src/__support/FPUtil/FPBits.h" -#include "src/__support/FPUtil/PolyEval.h" -#include "src/__support/FPUtil/double_double.h" -#include "src/__support/FPUtil/dyadic_float.h" -#include "src/__support/FPUtil/multiply_add.h" -#include "src/__support/FPUtil/nearest_integer.h" -#include "src/__support/FPUtil/rounding_mode.h" -#include "src/__support/FPUtil/triple_double.h" -#include "src/__support/common.h" -#include "src/__support/integer_literals.h" -#include "src/__support/macros/config.h" -#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY +#include "src/__support/math/exp10.h" namespace LIBC_NAMESPACE_DECL { -using fputil::DoubleDouble; -using fputil::TripleDouble; -using Float128 = typename fputil::DyadicFloat<128>; - -using LIBC_NAMESPACE::operator""_u128; - -// log2(10) -constexpr double LOG2_10 = 0x1.a934f0979a371p+1; - -// -2^-12 * log10(2) -// > a = -2^-12 * log10(2); -// > b = round(a, 32, RN); -// > c = round(a - b, 32, RN); -// > d = round(a - b - c, D, RN); -// Errors < 1.5 * 2^-144 -constexpr double MLOG10_2_EXP2_M12_HI = -0x1.3441350ap-14; -constexpr double MLOG10_2_EXP2_M12_MID = 0x1.0c0219dc1da99p-51; - -#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS -constexpr double MLOG10_2_EXP2_M12_MID_32 = 0x1.0c0219dcp-51; -constexpr double MLOG10_2_EXP2_M12_LO = 0x1.da994fd20dba2p-87; -#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS - -// Error bounds: -// Errors when using double precision. -constexpr double ERR_D = 0x1.8p-63; - -#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS -// Errors when using double-double precision. -constexpr double ERR_DD = 0x1.8p-99; -#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS - -namespace { - -// Polynomial approximations with double precision. Generated by Sollya with: -// > P = fpminimax((10^x - 1)/x, 3, [|D...|], [-2^-14, 2^-14]); -// > P; -// Error bounds: -// | output - (10^dx - 1) / dx | < 2^-52. -LIBC_INLINE double poly_approx_d(double dx) { - // dx^2 - double dx2 = dx * dx; - double c0 = - fputil::multiply_add(dx, 0x1.53524c73cea6ap+1, 0x1.26bb1bbb55516p+1); - double c1 = - fputil::multiply_add(dx, 0x1.2bd75cc6afc65p+0, 0x1.0470587aa264cp+1); - double p = fputil::multiply_add(dx2, c1, c0); - return p; -} - -#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS -// Polynomial approximation with double-double precision. Generated by Solya -// with: -// > P = fpminimax((10^x - 1)/x, 5, [|DD...|], [-2^-14, 2^-14]); -// Error bounds: -// | output - 10^(dx) | < 2^-101 -DoubleDouble poly_approx_dd(const DoubleDouble &dx) { - // Taylor polynomial. - constexpr DoubleDouble COEFFS[] = { - {0, 0x1p0}, - {-0x1.f48ad494e927bp-53, 0x1.26bb1bbb55516p1}, - {-0x1.e2bfab3191cd2p-53, 0x1.53524c73cea69p1}, - {0x1.80fb65ec3b503p-53, 0x1.0470591de2ca4p1}, - {0x1.338fc05e21e55p-54, 0x1.2bd7609fd98c4p0}, - {0x1.d4ea116818fbp-56, 0x1.1429ffd519865p-1}, - {-0x1.872a8ff352077p-57, 0x1.a7ed70847c8b3p-3}, - - }; - - DoubleDouble p = fputil::polyeval(dx, COEFFS[0], COEFFS[1], COEFFS[2], - COEFFS[3], COEFFS[4], COEFFS[5], COEFFS[6]); - return p; -} - -// Polynomial approximation with 128-bit precision: -// Return exp(dx) ~ 1 + a0 * dx + a1 * dx^2 + ... + a6 * dx^7 -// For |dx| < 2^-14: -// | output - 10^dx | < 1.5 * 2^-124. -Float128 poly_approx_f128(const Float128 &dx) { - constexpr Float128 COEFFS_128[]{ - {Sign::POS, -127, 0x80000000'00000000'00000000'00000000_u128}, // 1.0 - {Sign::POS, -126, 0x935d8ddd'aaa8ac16'ea56d62b'82d30a2d_u128}, - {Sign::POS, -126, 0xa9a92639'e753443a'80a99ce7'5f4d5bdb_u128}, - {Sign::POS, -126, 0x82382c8e'f1652304'6a4f9d7d'bf6c9635_u128}, - {Sign::POS, -124, 0x12bd7609'fd98c44c'34578701'9216c7af_u128}, - {Sign::POS, -127, 0x450a7ff4'7535d889'cc41ed7e'0d27aee5_u128}, - {Sign::POS, -130, 0xd3f6b844'702d636b'8326bb91'a6e7601d_u128}, - {Sign::POS, -130, 0x45b937f0'd05bb1cd'fa7b46df'314112a9_u128}, - }; - - Float128 p = fputil::polyeval(dx, COEFFS_128[0], COEFFS_128[1], COEFFS_128[2], - COEFFS_128[3], COEFFS_128[4], COEFFS_128[5], - COEFFS_128[6], COEFFS_128[7]); - return p; -} - -// Compute 10^(x) using 128-bit precision. -// TODO(lntue): investigate triple-double precision implementation for this -// step. -Float128 exp10_f128(double x, double kd, int idx1, int idx2) { - double t1 = fputil::multiply_add(kd, MLOG10_2_EXP2_M12_HI, x); // exact - double t2 = kd * MLOG10_2_EXP2_M12_MID_32; // exact - double t3 = kd * MLOG10_2_EXP2_M12_LO; // Error < 2^-144 - - Float128 dx = fputil::quick_add( - Float128(t1), fputil::quick_add(Float128(t2), Float128(t3))); - - // TODO: Skip recalculating exp_mid1 and exp_mid2. - Float128 exp_mid1 = - fputil::quick_add(Float128(EXP2_MID1[idx1].hi), - fputil::quick_add(Float128(EXP2_MID1[idx1].mid), - Float128(EXP2_MID1[idx1].lo))); - - Float128 exp_mid2 = - fputil::quick_add(Float128(EXP2_MID2[idx2].hi), - fputil::quick_add(Float128(EXP2_MID2[idx2].mid), - Float128(EXP2_MID2[idx2].lo))); - - Float128 exp_mid = fputil::quick_mul(exp_mid1, exp_mid2); - - Float128 p = poly_approx_f128(dx); - - Float128 r = fputil::quick_mul(exp_mid, p); - - r.exponent += static_cast(kd) >> 12; - - return r; -} - -// Compute 10^x with double-double precision. -DoubleDouble exp10_double_double(double x, double kd, - const DoubleDouble &exp_mid) { - // Recalculate dx: - // dx = x - k * 2^-12 * log10(2) - double t1 = fputil::multiply_add(kd, MLOG10_2_EXP2_M12_HI, x); // exact - double t2 = kd * MLOG10_2_EXP2_M12_MID_32; // exact - double t3 = kd * MLOG10_2_EXP2_M12_LO; // Error < 2^-140 - - DoubleDouble dx = fputil::exact_add(t1, t2); - dx.lo += t3; - - // Degree-6 polynomial approximation in double-double precision. - // | p - 10^x | < 2^-103. - DoubleDouble p = poly_approx_dd(dx); - - // Error bounds: 2^-102. - DoubleDouble r = fputil::quick_mult(exp_mid, p); - - return r; -} -#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS - -// When output is denormal. -double exp10_denorm(double x) { - // Range reduction. - double tmp = fputil::multiply_add(x, LOG2_10, 0x1.8000'0000'4p21); - int k = static_cast(cpp::bit_cast(tmp) >> 19); - double kd = static_cast(k); - - uint32_t idx1 = (k >> 6) & 0x3f; - uint32_t idx2 = k & 0x3f; - - int hi = k >> 12; - - DoubleDouble exp_mid1{EXP2_MID1[idx1].mid, EXP2_MID1[idx1].hi}; - DoubleDouble exp_mid2{EXP2_MID2[idx2].mid, EXP2_MID2[idx2].hi}; - DoubleDouble exp_mid = fputil::quick_mult(exp_mid1, exp_mid2); - - // |dx| < 1.5 * 2^-15 + 2^-31 < 2^-14 - double lo_h = fputil::multiply_add(kd, MLOG10_2_EXP2_M12_HI, x); // exact - double dx = fputil::multiply_add(kd, MLOG10_2_EXP2_M12_MID, lo_h); - - double mid_lo = dx * exp_mid.hi; - - // Approximate (10^dx - 1)/dx ~ 1 + a0*dx + a1*dx^2 + a2*dx^3 + a3*dx^4. - double p = poly_approx_d(dx); - - double lo = fputil::multiply_add(p, mid_lo, exp_mid.lo); - -#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS - return ziv_test_denorm(hi, exp_mid.hi, lo, ERR_D) - .value(); -#else - if (auto r = ziv_test_denorm(hi, exp_mid.hi, lo, ERR_D); - LIBC_LIKELY(r.has_value())) - return r.value(); - - // Use double-double - DoubleDouble r_dd = exp10_double_double(x, kd, exp_mid); - - if (auto r = ziv_test_denorm(hi, r_dd.hi, r_dd.lo, ERR_DD); - LIBC_LIKELY(r.has_value())) - return r.value(); - - // Use 128-bit precision - Float128 r_f128 = exp10_f128(x, kd, idx1, idx2); - - return static_cast(r_f128); -#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS -} - -// Check for exceptional cases when: -// * log10(1 - 2^-54) < x < log10(1 + 2^-53) -// * x >= log10(2^1024) -// * x <= log10(2^-1022) -// * x is inf or nan -double set_exceptional(double x) { - using FPBits = typename fputil::FPBits; - FPBits xbits(x); - - uint64_t x_u = xbits.uintval(); - uint64_t x_abs = xbits.abs().uintval(); - - // |x| < log10(1 + 2^-53) - if (x_abs <= 0x3c8bcb7b1526e50e) { - // 10^(x) ~ 1 + x/2 - return fputil::multiply_add(x, 0.5, 1.0); - } - - // x <= log10(2^-1022) || x >= log10(2^1024) or inf/nan. - if (x_u >= 0xc0733a7146f72a42) { - // x <= log10(2^-1075) or -inf/nan - if (x_u > 0xc07439b746e36b52) { - // exp(-Inf) = 0 - if (xbits.is_inf()) - return 0.0; - - // exp(nan) = nan - if (xbits.is_nan()) - return x; - - if (fputil::quick_get_round() == FE_UPWARD) - return FPBits::min_subnormal().get_val(); - fputil::set_errno_if_required(ERANGE); - fputil::raise_except_if_required(FE_UNDERFLOW); - return 0.0; - } - - return exp10_denorm(x); - } - - // x >= log10(2^1024) or +inf/nan - // x is finite - if (x_u < 0x7ff0'0000'0000'0000ULL) { - int rounding = fputil::quick_get_round(); - if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO) - return FPBits::max_normal().get_val(); - - fputil::set_errno_if_required(ERANGE); - fputil::raise_except_if_required(FE_OVERFLOW); - } - // x is +inf or nan - return x + FPBits::inf().get_val(); -} - -} // namespace - -LLVM_LIBC_FUNCTION(double, exp10, (double x)) { - using FPBits = typename fputil::FPBits; - FPBits xbits(x); - - uint64_t x_u = xbits.uintval(); - - // x <= log10(2^-1022) or x >= log10(2^1024) or - // log10(1 - 2^-54) < x < log10(1 + 2^-53). - if (LIBC_UNLIKELY(x_u >= 0xc0733a7146f72a42 || - (x_u <= 0xbc7bcb7b1526e50e && x_u >= 0x40734413509f79ff) || - x_u < 0x3c8bcb7b1526e50e)) { - return set_exceptional(x); - } - - // Now log10(2^-1075) < x <= log10(1 - 2^-54) or - // log10(1 + 2^-53) < x < log10(2^1024) - - // Range reduction: - // Let x = log10(2) * (hi + mid1 + mid2) + lo - // in which: - // hi is an integer - // mid1 * 2^6 is an integer - // mid2 * 2^12 is an integer - // then: - // 10^(x) = 2^hi * 2^(mid1) * 2^(mid2) * 10^(lo). - // With this formula: - // - multiplying by 2^hi is exact and cheap, simply by adding the exponent - // field. - // - 2^(mid1) and 2^(mid2) are stored in 2 x 64-element tables. - // - 10^(lo) ~ 1 + a0*lo + a1 * lo^2 + ... - // - // We compute (hi + mid1 + mid2) together by perform the rounding on - // x * log2(10) * 2^12. - // Since |x| < |log10(2^-1075)| < 2^9, - // |x * 2^12| < 2^9 * 2^12 < 2^21, - // So we can fit the rounded result round(x * 2^12) in int32_t. - // Thus, the goal is to be able to use an additional addition and fixed width - // shift to get an int32_t representing round(x * 2^12). - // - // Assuming int32_t using 2-complement representation, since the mantissa part - // of a double precision is unsigned with the leading bit hidden, if we add an - // extra constant C = 2^e1 + 2^e2 with e1 > e2 >= 2^23 to the product, the - // part that are < 2^e2 in resulted mantissa of (x*2^12*L2E + C) can be - // considered as a proper 2-complement representations of x*2^12. - // - // One small problem with this approach is that the sum (x*2^12 + C) in - // double precision is rounded to the least significant bit of the dorminant - // factor C. In order to minimize the rounding errors from this addition, we - // want to minimize e1. Another constraint that we want is that after - // shifting the mantissa so that the least significant bit of int32_t - // corresponds to the unit bit of (x*2^12*L2E), the sign is correct without - // any adjustment. So combining these 2 requirements, we can choose - // C = 2^33 + 2^32, so that the sign bit corresponds to 2^31 bit, and hence - // after right shifting the mantissa, the resulting int32_t has correct sign. - // With this choice of C, the number of mantissa bits we need to shift to the - // right is: 52 - 33 = 19. - // - // Moreover, since the integer right shifts are equivalent to rounding down, - // we can add an extra 0.5 so that it will become round-to-nearest, tie-to- - // +infinity. So in particular, we can compute: - // hmm = x * 2^12 + C, - // where C = 2^33 + 2^32 + 2^-1, then if - // k = int32_t(lower 51 bits of double(x * 2^12 + C) >> 19), - // the reduced argument: - // lo = x - log10(2) * 2^-12 * k is bounded by: - // |lo| = |x - log10(2) * 2^-12 * k| - // = log10(2) * 2^-12 * | x * log2(10) * 2^12 - k | - // <= log10(2) * 2^-12 * (2^-1 + 2^-19) - // < 1.5 * 2^-2 * (2^-13 + 2^-31) - // = 1.5 * (2^-15 * 2^-31) - // - // Finally, notice that k only uses the mantissa of x * 2^12, so the - // exponent 2^12 is not needed. So we can simply define - // C = 2^(33 - 12) + 2^(32 - 12) + 2^(-13 - 12), and - // k = int32_t(lower 51 bits of double(x + C) >> 19). - - // Rounding errors <= 2^-31. - double tmp = fputil::multiply_add(x, LOG2_10, 0x1.8000'0000'4p21); - int k = static_cast(cpp::bit_cast(tmp) >> 19); - double kd = static_cast(k); - - uint32_t idx1 = (k >> 6) & 0x3f; - uint32_t idx2 = k & 0x3f; - - int hi = k >> 12; - - DoubleDouble exp_mid1{EXP2_MID1[idx1].mid, EXP2_MID1[idx1].hi}; - DoubleDouble exp_mid2{EXP2_MID2[idx2].mid, EXP2_MID2[idx2].hi}; - DoubleDouble exp_mid = fputil::quick_mult(exp_mid1, exp_mid2); - - // |dx| < 1.5 * 2^-15 + 2^-31 < 2^-14 - double lo_h = fputil::multiply_add(kd, MLOG10_2_EXP2_M12_HI, x); // exact - double dx = fputil::multiply_add(kd, MLOG10_2_EXP2_M12_MID, lo_h); - - // We use the degree-4 polynomial to approximate 10^(lo): - // 10^(lo) ~ 1 + a0 * lo + a1 * lo^2 + a2 * lo^3 + a3 * lo^4 - // = 1 + lo * P(lo) - // So that the errors are bounded by: - // |P(lo) - (10^lo - 1)/lo| < |lo|^4 / 64 < 2^(-13 * 4) / 64 = 2^-58 - // Let P_ be an evaluation of P where all intermediate computations are in - // double precision. Using either Horner's or Estrin's schemes, the evaluated - // errors can be bounded by: - // |P_(lo) - P(lo)| < 2^-51 - // => |lo * P_(lo) - (2^lo - 1) | < 2^-65 - // => 2^(mid1 + mid2) * |lo * P_(lo) - expm1(lo)| < 2^-64. - // Since we approximate - // 2^(mid1 + mid2) ~ exp_mid.hi + exp_mid.lo, - // We use the expression: - // (exp_mid.hi + exp_mid.lo) * (1 + dx * P_(dx)) ~ - // ~ exp_mid.hi + (exp_mid.hi * dx * P_(dx) + exp_mid.lo) - // with errors bounded by 2^-64. - - double mid_lo = dx * exp_mid.hi; - - // Approximate (10^dx - 1)/dx ~ 1 + a0*dx + a1*dx^2 + a2*dx^3 + a3*dx^4. - double p = poly_approx_d(dx); - - double lo = fputil::multiply_add(p, mid_lo, exp_mid.lo); - -#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS - int64_t exp_hi = static_cast(hi) << FPBits::FRACTION_LEN; - double r = - cpp::bit_cast(exp_hi + cpp::bit_cast(exp_mid.hi + lo)); - return r; -#else - double upper = exp_mid.hi + (lo + ERR_D); - double lower = exp_mid.hi + (lo - ERR_D); - - if (LIBC_LIKELY(upper == lower)) { - // To multiply by 2^hi, a fast way is to simply add hi to the exponent - // field. - int64_t exp_hi = static_cast(hi) << FPBits::FRACTION_LEN; - double r = cpp::bit_cast(exp_hi + cpp::bit_cast(upper)); - return r; - } - - // Exact outputs when x = 1, 2, ..., 22 + hard to round with x = 23. - // Quick check mask: 0x800f'ffffU = ~(bits of 1.0 | ... | bits of 23.0) - if (LIBC_UNLIKELY((x_u & 0x8000'ffff'ffff'ffffULL) == 0ULL)) { - switch (x_u) { - case 0x3ff0000000000000: // x = 1.0 - return 10.0; - case 0x4000000000000000: // x = 2.0 - return 100.0; - case 0x4008000000000000: // x = 3.0 - return 1'000.0; - case 0x4010000000000000: // x = 4.0 - return 10'000.0; - case 0x4014000000000000: // x = 5.0 - return 100'000.0; - case 0x4018000000000000: // x = 6.0 - return 1'000'000.0; - case 0x401c000000000000: // x = 7.0 - return 10'000'000.0; - case 0x4020000000000000: // x = 8.0 - return 100'000'000.0; - case 0x4022000000000000: // x = 9.0 - return 1'000'000'000.0; - case 0x4024000000000000: // x = 10.0 - return 10'000'000'000.0; - case 0x4026000000000000: // x = 11.0 - return 100'000'000'000.0; - case 0x4028000000000000: // x = 12.0 - return 1'000'000'000'000.0; - case 0x402a000000000000: // x = 13.0 - return 10'000'000'000'000.0; - case 0x402c000000000000: // x = 14.0 - return 100'000'000'000'000.0; - case 0x402e000000000000: // x = 15.0 - return 1'000'000'000'000'000.0; - case 0x4030000000000000: // x = 16.0 - return 10'000'000'000'000'000.0; - case 0x4031000000000000: // x = 17.0 - return 100'000'000'000'000'000.0; - case 0x4032000000000000: // x = 18.0 - return 1'000'000'000'000'000'000.0; - case 0x4033000000000000: // x = 19.0 - return 10'000'000'000'000'000'000.0; - case 0x4034000000000000: // x = 20.0 - return 100'000'000'000'000'000'000.0; - case 0x4035000000000000: // x = 21.0 - return 1'000'000'000'000'000'000'000.0; - case 0x4036000000000000: // x = 22.0 - return 10'000'000'000'000'000'000'000.0; - case 0x4037000000000000: // x = 23.0 - return 0x1.52d02c7e14af6p76 + x; - } - } - - // Use double-double - DoubleDouble r_dd = exp10_double_double(x, kd, exp_mid); - - double upper_dd = r_dd.hi + (r_dd.lo + ERR_DD); - double lower_dd = r_dd.hi + (r_dd.lo - ERR_DD); - - if (LIBC_LIKELY(upper_dd == lower_dd)) { - // To multiply by 2^hi, a fast way is to simply add hi to the exponent - // field. - int64_t exp_hi = static_cast(hi) << FPBits::FRACTION_LEN; - double r = cpp::bit_cast(exp_hi + cpp::bit_cast(upper_dd)); - return r; - } - - // Use 128-bit precision - Float128 r_f128 = exp10_f128(x, kd, idx1, idx2); - - return static_cast(r_f128); -#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS -} +LLVM_LIBC_FUNCTION(double, exp10, (double x)) { return math::exp10(x); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/exp10f.cpp b/libc/src/math/generic/exp10f.cpp index 5284c380f52ec..b2d4f097bc7ce 100644 --- a/libc/src/math/generic/exp10f.cpp +++ b/libc/src/math/generic/exp10f.cpp @@ -7,12 +7,11 @@ //===----------------------------------------------------------------------===// #include "src/math/exp10f.h" -#include "src/__support/common.h" -#include "src/__support/macros/config.h" -#include "src/math/generic/exp10f_impl.h" + +#include "src/__support/math/exp10f.h" namespace LIBC_NAMESPACE_DECL { -LLVM_LIBC_FUNCTION(float, exp10f, (float x)) { return generic::exp10f(x); } +LLVM_LIBC_FUNCTION(float, exp10f, (float x)) { return math::exp10f(x); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/exp10f16.cpp b/libc/src/math/generic/exp10f16.cpp index 31abf3b4f89b2..cb3c8599c9231 100644 --- a/libc/src/math/generic/exp10f16.cpp +++ b/libc/src/math/generic/exp10f16.cpp @@ -7,128 +7,10 @@ //===----------------------------------------------------------------------===// #include "src/math/exp10f16.h" -#include "expxf16.h" -#include "hdr/errno_macros.h" -#include "hdr/fenv_macros.h" -#include "src/__support/CPP/array.h" -#include "src/__support/FPUtil/FEnvImpl.h" -#include "src/__support/FPUtil/FPBits.h" -#include "src/__support/FPUtil/PolyEval.h" -#include "src/__support/FPUtil/cast.h" -#include "src/__support/FPUtil/except_value_utils.h" -#include "src/__support/FPUtil/multiply_add.h" -#include "src/__support/FPUtil/nearest_integer.h" -#include "src/__support/FPUtil/rounding_mode.h" -#include "src/__support/common.h" -#include "src/__support/macros/config.h" -#include "src/__support/macros/optimization.h" -#include "src/__support/macros/properties/cpu_features.h" +#include "src/__support/math/exp10f16.h" namespace LIBC_NAMESPACE_DECL { -#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS -#ifdef LIBC_TARGET_CPU_HAS_FMA_FLOAT -static constexpr size_t N_EXP10F16_EXCEPTS = 5; -#else -static constexpr size_t N_EXP10F16_EXCEPTS = 8; -#endif - -static constexpr fputil::ExceptValues - EXP10F16_EXCEPTS = {{ - // x = 0x1.8f4p-2, exp10f16(x) = 0x1.3ap+1 (RZ) - {0x363dU, 0x40e8U, 1U, 0U, 1U}, - // x = 0x1.95cp-2, exp10f16(x) = 0x1.3ecp+1 (RZ) - {0x3657U, 0x40fbU, 1U, 0U, 0U}, - // x = -0x1.018p-4, exp10f16(x) = 0x1.bbp-1 (RZ) - {0xac06U, 0x3aecU, 1U, 0U, 0U}, - // x = -0x1.c28p+0, exp10f16(x) = 0x1.1ccp-6 (RZ) - {0xbf0aU, 0x2473U, 1U, 0U, 0U}, - // x = -0x1.e1cp+1, exp10f16(x) = 0x1.694p-13 (RZ) - {0xc387U, 0x09a5U, 1U, 0U, 0U}, -#ifndef LIBC_TARGET_CPU_HAS_FMA_FLOAT - // x = 0x1.0cp+1, exp10f16(x) = 0x1.f04p+6 (RZ) - {0x4030U, 0x57c1U, 1U, 0U, 1U}, - // x = 0x1.1b8p+1, exp10f16(x) = 0x1.47cp+7 (RZ) - {0x406eU, 0x591fU, 1U, 0U, 1U}, - // x = 0x1.1b8p+2, exp10f16(x) = 0x1.a4p+14 (RZ) - {0x446eU, 0x7690U, 1U, 0U, 1U}, -#endif - }}; -#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS - -LLVM_LIBC_FUNCTION(float16, exp10f16, (float16 x)) { - using FPBits = fputil::FPBits; - FPBits x_bits(x); - - uint16_t x_u = x_bits.uintval(); - uint16_t x_abs = x_u & 0x7fffU; - - // When |x| >= 5, or x is NaN. - if (LIBC_UNLIKELY(x_abs >= 0x4500U)) { - // exp10(NaN) = NaN - if (x_bits.is_nan()) { - if (x_bits.is_signaling_nan()) { - fputil::raise_except_if_required(FE_INVALID); - return FPBits::quiet_nan().get_val(); - } - - return x; - } - - // When x >= 5. - if (x_bits.is_pos()) { - // exp10(+inf) = +inf - if (x_bits.is_inf()) - return FPBits::inf().get_val(); - - switch (fputil::quick_get_round()) { - case FE_TONEAREST: - case FE_UPWARD: - fputil::set_errno_if_required(ERANGE); - fputil::raise_except_if_required(FE_OVERFLOW); - return FPBits::inf().get_val(); - default: - return FPBits::max_normal().get_val(); - } - } - - // When x <= -8. - if (x_u >= 0xc800U) { - // exp10(-inf) = +0 - if (x_bits.is_inf()) - return FPBits::zero().get_val(); - - fputil::set_errno_if_required(ERANGE); - fputil::raise_except_if_required(FE_UNDERFLOW | FE_INEXACT); - - if (fputil::fenv_is_round_up()) - return FPBits::min_subnormal().get_val(); - return FPBits::zero().get_val(); - } - } - - // When x is 1, 2, 3, or 4. These are hard-to-round cases with exact results. - if (LIBC_UNLIKELY((x_u & ~(0x3c00U | 0x4000U | 0x4200U | 0x4400U)) == 0)) { - switch (x_u) { - case 0x3c00U: // x = 1.0f16 - return fputil::cast(10.0); - case 0x4000U: // x = 2.0f16 - return fputil::cast(100.0); - case 0x4200U: // x = 3.0f16 - return fputil::cast(1'000.0); - case 0x4400U: // x = 4.0f16 - return fputil::cast(10'000.0); - } - } - -#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS - if (auto r = EXP10F16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value())) - return r.value(); -#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS - - // 10^x = 2^((hi + mid) * log2(10)) * 10^lo - auto [exp2_hi_mid, exp10_lo] = exp10_range_reduction(x); - return fputil::cast(exp2_hi_mid * exp10_lo); -} +LLVM_LIBC_FUNCTION(float16, exp10f16, (float16 x)) { return math::exp10f16(x); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/exp10m1f16.cpp b/libc/src/math/generic/exp10m1f16.cpp index 545c479694811..6c2fdbea418df 100644 --- a/libc/src/math/generic/exp10m1f16.cpp +++ b/libc/src/math/generic/exp10m1f16.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "src/math/exp10m1f16.h" -#include "expxf16.h" #include "hdr/errno_macros.h" #include "hdr/fenv_macros.h" #include "src/__support/FPUtil/FEnvImpl.h" @@ -21,6 +20,7 @@ #include "src/__support/macros/config.h" #include "src/__support/macros/optimization.h" #include "src/__support/macros/properties/cpu_features.h" +#include "src/__support/math/exp10f16_utils.h" namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/math/generic/explogxf.cpp b/libc/src/math/generic/explogxf.cpp deleted file mode 100644 index d38efa0269693..0000000000000 --- a/libc/src/math/generic/explogxf.cpp +++ /dev/null @@ -1,75 +0,0 @@ -//===-- Single-precision general exp/log functions ------------------------===// -// -// 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 "explogxf.h" -#include "src/__support/macros/config.h" - -namespace LIBC_NAMESPACE_DECL { - -// N[Table[Log[2, 1 + x], {x, 0/64, 63/64, 1/64}], 40] -alignas(8) const double LOG_P1_LOG2[LOG_P1_SIZE] = { - 0x0.0000000000000p+0, 0x1.6e79685c2d22ap-6, 0x1.6bad3758efd87p-5, - 0x1.0eb389fa29f9bp-4, 0x1.663f6fac91316p-4, 0x1.bc84240adabbap-4, - 0x1.08c588cda79e4p-3, 0x1.32ae9e278ae1ap-3, 0x1.5c01a39fbd688p-3, - 0x1.84c2bd02f03b3p-3, 0x1.acf5e2db4ec94p-3, 0x1.d49ee4c325970p-3, - 0x1.fbc16b902680ap-3, 0x1.11307dad30b76p-2, 0x1.24407ab0e073ap-2, - 0x1.37124cea4cdedp-2, 0x1.49a784bcd1b8bp-2, 0x1.5c01a39fbd688p-2, - 0x1.6e221cd9d0cdep-2, 0x1.800a563161c54p-2, 0x1.91bba891f1709p-2, - 0x1.a33760a7f6051p-2, 0x1.b47ebf73882a1p-2, 0x1.c592fad295b56p-2, - 0x1.d6753e032ea0fp-2, 0x1.e726aa1e754d2p-2, 0x1.f7a8568cb06cfp-2, - 0x1.03fda8b97997fp-1, 0x1.0c10500d63aa6p-1, 0x1.140c9faa1e544p-1, - 0x1.1bf311e95d00ep-1, 0x1.23c41d42727c8p-1, 0x1.2b803473f7ad1p-1, - 0x1.3327c6ab49ca7p-1, 0x1.3abb3faa02167p-1, 0x1.423b07e986aa9p-1, - 0x1.49a784bcd1b8bp-1, 0x1.510118708a8f9p-1, 0x1.5848226989d34p-1, - 0x1.5f7cff41e09afp-1, 0x1.66a008e4788ccp-1, 0x1.6db196a76194ap-1, - 0x1.74b1fd64e0754p-1, 0x1.7ba18f93502e4p-1, 0x1.82809d5be7073p-1, - 0x1.894f74b06ef8bp-1, 0x1.900e6160002cdp-1, 0x1.96bdad2acb5f6p-1, - 0x1.9d5d9fd5010b3p-1, 0x1.a3ee7f38e181fp-1, 0x1.aa708f58014d3p-1, - 0x1.b0e4126bcc86cp-1, 0x1.b74948f5532dap-1, 0x1.bda071cc67e6ep-1, - 0x1.c3e9ca2e1a055p-1, 0x1.ca258dca93316p-1, 0x1.d053f6d260896p-1, - 0x1.d6753e032ea0fp-1, 0x1.dc899ab3ff56cp-1, 0x1.e29142e0e0140p-1, - 0x1.e88c6b3626a73p-1, 0x1.ee7b471b3a950p-1, 0x1.f45e08bcf0655p-1, - 0x1.fa34e1177c233p-1, -}; - -// N[Table[1/(1 + x), {x, 0/64, 63/64, 1/64}], 40] -alignas(8) const double LOG_P1_1_OVER[LOG_P1_SIZE] = { - 0x1.0000000000000p+0, 0x1.f81f81f81f820p-1, 0x1.f07c1f07c1f08p-1, - 0x1.e9131abf0b767p-1, 0x1.e1e1e1e1e1e1ep-1, 0x1.dae6076b981dbp-1, - 0x1.d41d41d41d41dp-1, 0x1.cd85689039b0bp-1, 0x1.c71c71c71c71cp-1, - 0x1.c0e070381c0e0p-1, 0x1.bacf914c1bad0p-1, 0x1.b4e81b4e81b4fp-1, - 0x1.af286bca1af28p-1, 0x1.a98ef606a63bep-1, 0x1.a41a41a41a41ap-1, - 0x1.9ec8e951033d9p-1, 0x1.999999999999ap-1, 0x1.948b0fcd6e9e0p-1, - 0x1.8f9c18f9c18fap-1, 0x1.8acb90f6bf3aap-1, 0x1.8618618618618p-1, - 0x1.8181818181818p-1, 0x1.7d05f417d05f4p-1, 0x1.78a4c8178a4c8p-1, - 0x1.745d1745d1746p-1, 0x1.702e05c0b8170p-1, 0x1.6c16c16c16c17p-1, - 0x1.6816816816817p-1, 0x1.642c8590b2164p-1, 0x1.6058160581606p-1, - 0x1.5c9882b931057p-1, 0x1.58ed2308158edp-1, 0x1.5555555555555p-1, - 0x1.51d07eae2f815p-1, 0x1.4e5e0a72f0539p-1, 0x1.4afd6a052bf5bp-1, - 0x1.47ae147ae147bp-1, 0x1.446f86562d9fbp-1, 0x1.4141414141414p-1, - 0x1.3e22cbce4a902p-1, 0x1.3b13b13b13b14p-1, 0x1.3813813813814p-1, - 0x1.3521cfb2b78c1p-1, 0x1.323e34a2b10bfp-1, 0x1.2f684bda12f68p-1, - 0x1.2c9fb4d812ca0p-1, 0x1.29e4129e4129ep-1, 0x1.27350b8812735p-1, - 0x1.2492492492492p-1, 0x1.21fb78121fb78p-1, 0x1.1f7047dc11f70p-1, - 0x1.1cf06ada2811dp-1, 0x1.1a7b9611a7b96p-1, 0x1.1811811811812p-1, - 0x1.15b1e5f75270dp-1, 0x1.135c81135c811p-1, 0x1.1111111111111p-1, - 0x1.0ecf56be69c90p-1, 0x1.0c9714fbcda3bp-1, 0x1.0a6810a6810a7p-1, - 0x1.0842108421084p-1, 0x1.0624dd2f1a9fcp-1, 0x1.0410410410410p-1, - 0x1.0204081020408p-1}; - -// Taylos series expansion for Log[2, 1 + x] splitted to EVEN AND ODD numbers -// K_LOG2_ODD starts from x^3 -alignas(8) const - double K_LOG2_ODD[4] = {0x1.ec709dc3a03fdp-2, 0x1.2776c50ef9bfep-2, - 0x1.a61762a7aded9p-3, 0x1.484b13d7c02a9p-3}; - -alignas(8) const - double K_LOG2_EVEN[4] = {-0x1.71547652b82fep-1, -0x1.71547652b82fep-2, - -0x1.ec709dc3a03fdp-3, -0x1.2776c50ef9bfep-3}; - -} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/explogxf.h b/libc/src/math/generic/explogxf.h index 5ae1457ca780e..a2a6d60f41f76 100644 --- a/libc/src/math/generic/explogxf.h +++ b/libc/src/math/generic/explogxf.h @@ -10,166 +10,18 @@ #define LLVM_LIBC_SRC_MATH_GENERIC_EXPLOGXF_H #include "common_constants.h" -#include "src/__support/FPUtil/FEnvImpl.h" -#include "src/__support/FPUtil/PolyEval.h" -#include "src/__support/FPUtil/nearest_integer.h" + #include "src/__support/common.h" -#include "src/__support/macros/config.h" #include "src/__support/macros/properties/cpu_features.h" - +#include "src/__support/math/acoshf_utils.h" +#include "src/__support/math/exp10f_utils.h" #include "src/__support/math/exp_utils.h" namespace LIBC_NAMESPACE_DECL { -struct ExpBase { - // Base = e - static constexpr int MID_BITS = 5; - static constexpr int MID_MASK = (1 << MID_BITS) - 1; - // log2(e) * 2^5 - static constexpr double LOG2_B = 0x1.71547652b82fep+0 * (1 << MID_BITS); - // High and low parts of -log(2) * 2^(-5) - static constexpr double M_LOGB_2_HI = -0x1.62e42fefa0000p-1 / (1 << MID_BITS); - static constexpr double M_LOGB_2_LO = - -0x1.cf79abc9e3b3ap-40 / (1 << MID_BITS); - // Look up table for bit fields of 2^(i/32) for i = 0..31, generated by Sollya - // with: - // > for i from 0 to 31 do printdouble(round(2^(i/32), D, RN)); - static constexpr int64_t EXP_2_MID[1 << MID_BITS] = { - 0x3ff0000000000000, 0x3ff059b0d3158574, 0x3ff0b5586cf9890f, - 0x3ff11301d0125b51, 0x3ff172b83c7d517b, 0x3ff1d4873168b9aa, - 0x3ff2387a6e756238, 0x3ff29e9df51fdee1, 0x3ff306fe0a31b715, - 0x3ff371a7373aa9cb, 0x3ff3dea64c123422, 0x3ff44e086061892d, - 0x3ff4bfdad5362a27, 0x3ff5342b569d4f82, 0x3ff5ab07dd485429, - 0x3ff6247eb03a5585, 0x3ff6a09e667f3bcd, 0x3ff71f75e8ec5f74, - 0x3ff7a11473eb0187, 0x3ff82589994cce13, 0x3ff8ace5422aa0db, - 0x3ff93737b0cdc5e5, 0x3ff9c49182a3f090, 0x3ffa5503b23e255d, - 0x3ffae89f995ad3ad, 0x3ffb7f76f2fb5e47, 0x3ffc199bdd85529c, - 0x3ffcb720dcef9069, 0x3ffd5818dcfba487, 0x3ffdfc97337b9b5f, - 0x3ffea4afa2a490da, 0x3fff50765b6e4540, - }; - - // Approximating e^dx with degree-5 minimax polynomial generated by Sollya: - // > Q = fpminimax(expm1(x)/x, 4, [|1, D...|], [-log(2)/64, log(2)/64]); - // Then: - // e^dx ~ P(dx) = 1 + dx + COEFFS[0] * dx^2 + ... + COEFFS[3] * dx^5. - static constexpr double COEFFS[4] = { - 0x1.ffffffffe5bc8p-2, 0x1.555555555cd67p-3, 0x1.5555c2a9b48b4p-5, - 0x1.11112a0e34bdbp-7}; - - LIBC_INLINE static double powb_lo(double dx) { - using fputil::multiply_add; - double dx2 = dx * dx; - double c0 = 1.0 + dx; - // c1 = COEFFS[0] + COEFFS[1] * dx - double c1 = multiply_add(dx, ExpBase::COEFFS[1], ExpBase::COEFFS[0]); - // c2 = COEFFS[2] + COEFFS[3] * dx - double c2 = multiply_add(dx, ExpBase::COEFFS[3], ExpBase::COEFFS[2]); - // r = c4 + c5 * dx^4 - // = 1 + dx + COEFFS[0] * dx^2 + ... + COEFFS[5] * dx^7 - return fputil::polyeval(dx2, c0, c1, c2); - } -}; - -struct Exp10Base : public ExpBase { - // log2(10) * 2^5 - static constexpr double LOG2_B = 0x1.a934f0979a371p1 * (1 << MID_BITS); - // High and low parts of -log10(2) * 2^(-5). - // Notice that since |x * log2(10)| < 150: - // |k| = |round(x * log2(10) * 2^5)| < 2^8 * 2^5 = 2^13 - // So when the FMA instructions are not available, in order for the product - // k * M_LOGB_2_HI - // to be exact, we only store the high part of log10(2) up to 38 bits - // (= 53 - 15) of precision. - // It is generated by Sollya with: - // > round(log10(2), 44, RN); - static constexpr double M_LOGB_2_HI = -0x1.34413509f8p-2 / (1 << MID_BITS); - // > round(log10(2) - 0x1.34413509f8p-2, D, RN); - static constexpr double M_LOGB_2_LO = 0x1.80433b83b532ap-44 / (1 << MID_BITS); - - // Approximating 10^dx with degree-5 minimax polynomial generated by Sollya: - // > Q = fpminimax((10^x - 1)/x, 4, [|D...|], [-log10(2)/2^6, log10(2)/2^6]); - // Then: - // 10^dx ~ P(dx) = 1 + COEFFS[0] * dx + ... + COEFFS[4] * dx^5. - static constexpr double COEFFS[5] = {0x1.26bb1bbb55515p1, 0x1.53524c73bd3eap1, - 0x1.0470591dff149p1, 0x1.2bd7c0a9fbc4dp0, - 0x1.1429e74a98f43p-1}; - - static double powb_lo(double dx) { - using fputil::multiply_add; - double dx2 = dx * dx; - // c0 = 1 + COEFFS[0] * dx - double c0 = multiply_add(dx, Exp10Base::COEFFS[0], 1.0); - // c1 = COEFFS[1] + COEFFS[2] * dx - double c1 = multiply_add(dx, Exp10Base::COEFFS[2], Exp10Base::COEFFS[1]); - // c2 = COEFFS[3] + COEFFS[4] * dx - double c2 = multiply_add(dx, Exp10Base::COEFFS[4], Exp10Base::COEFFS[3]); - // r = c0 + dx^2 * (c1 + c2 * dx^2) - // = c0 + c1 * dx^2 + c2 * dx^4 - // = 1 + COEFFS[0] * dx + ... + COEFFS[4] * dx^5. - return fputil::polyeval(dx2, c0, c1, c2); - } -}; - constexpr int LOG_P1_BITS = 6; constexpr int LOG_P1_SIZE = 1 << LOG_P1_BITS; -// N[Table[Log[2, 1 + x], {x, 0/64, 63/64, 1/64}], 40] -extern const double LOG_P1_LOG2[LOG_P1_SIZE]; - -// N[Table[1/(1 + x), {x, 0/64, 63/64, 1/64}], 40] -extern const double LOG_P1_1_OVER[LOG_P1_SIZE]; - -// Taylor series expansion for Log[2, 1 + x] splitted to EVEN AND ODD numbers -// K_LOG2_ODD starts from x^3 -extern const double K_LOG2_ODD[4]; -extern const double K_LOG2_EVEN[4]; - -// Output of range reduction for exp_b: (2^(mid + hi), lo) -// where: -// b^x = 2^(mid + hi) * b^lo -struct exp_b_reduc_t { - double mh; // 2^(mid + hi) - double lo; -}; - -// The function correctly calculates b^x value with at least float precision -// in a limited range. -// Range reduction: -// b^x = 2^(hi + mid) * b^lo -// where: -// x = (hi + mid) * log_b(2) + lo -// hi is an integer, -// 0 <= mid * 2^MID_BITS < 2^MID_BITS is an integer -// -2^(-MID_BITS - 1) <= lo * log2(b) <= 2^(-MID_BITS - 1) -// Base class needs to provide the following constants: -// - MID_BITS : number of bits after decimal points used for mid -// - MID_MASK : 2^MID_BITS - 1, mask to extract mid bits -// - LOG2_B : log2(b) * 2^MID_BITS for scaling -// - M_LOGB_2_HI : high part of -log_b(2) * 2^(-MID_BITS) -// - M_LOGB_2_LO : low part of -log_b(2) * 2^(-MID_BITS) -// - EXP_2_MID : look up table for bit fields of 2^mid -// Return: -// { 2^(hi + mid), lo } -template LIBC_INLINE exp_b_reduc_t exp_b_range_reduc(float x) { - double xd = static_cast(x); - // kd = round((hi + mid) * log2(b) * 2^MID_BITS) - double kd = fputil::nearest_integer(Base::LOG2_B * xd); - // k = round((hi + mid) * log2(b) * 2^MID_BITS) - int k = static_cast(kd); - // hi = floor(kd * 2^(-MID_BITS)) - // exp_hi = shift hi to the exponent field of double precision. - uint64_t exp_hi = static_cast(k >> Base::MID_BITS) - << fputil::FPBits::FRACTION_LEN; - // mh = 2^hi * 2^mid - // mh_bits = bit field of mh - uint64_t mh_bits = Base::EXP_2_MID[k & Base::MID_MASK] + exp_hi; - double mh = fputil::FPBits(mh_bits).get_val(); - // dx = lo = x - (hi + mid) * log(2) - double dx = fputil::multiply_add( - kd, Base::M_LOGB_2_LO, fputil::multiply_add(kd, Base::M_LOGB_2_HI, xd)); - return {mh, dx}; -} - // The function correctly calculates sinh(x) and cosh(x) by calculating exp(x) // and exp(-x) simultaneously. // To compute e^x, we perform the following range @@ -269,33 +121,6 @@ template LIBC_INLINE double exp_pm_eval(float x) { return r; } -// x should be positive, normal finite value -LIBC_INLINE static double log2_eval(double x) { - using FPB = fputil::FPBits; - FPB bs(x); - - double result = 0; - result += bs.get_exponent(); - - int p1 = (bs.get_mantissa() >> (FPB::FRACTION_LEN - LOG_P1_BITS)) & - (LOG_P1_SIZE - 1); - - bs.set_uintval(bs.uintval() & (FPB::FRACTION_MASK >> LOG_P1_BITS)); - bs.set_biased_exponent(FPB::EXP_BIAS); - double dx = (bs.get_val() - 1.0) * LOG_P1_1_OVER[p1]; - - // Taylor series for log(2,1+x) - double c1 = fputil::multiply_add(dx, K_LOG2_ODD[0], K_LOG2_EVEN[0]); - double c2 = fputil::multiply_add(dx, K_LOG2_ODD[1], K_LOG2_EVEN[1]); - double c3 = fputil::multiply_add(dx, K_LOG2_ODD[2], K_LOG2_EVEN[2]); - double c4 = fputil::multiply_add(dx, K_LOG2_ODD[3], K_LOG2_EVEN[3]); - - // c0 = dx * (1.0 / ln(2)) + LOG_P1_LOG2[p1] - double c0 = fputil::multiply_add(dx, 0x1.71547652b82fep+0, LOG_P1_LOG2[p1]); - result += LIBC_NAMESPACE::fputil::polyeval(dx * dx, c0, c1, c2, c3, c4); - return result; -} - // x should be positive, normal finite value // TODO: Simplify range reduction and polynomial degree for float16. // See issue #137190. @@ -339,41 +164,6 @@ LIBC_INLINE static float log_eval_f(float x) { return result; } -// x should be positive, normal finite value -LIBC_INLINE static double log_eval(double x) { - // For x = 2^ex * (1 + mx) - // log(x) = ex * log(2) + log(1 + mx) - using FPB = fputil::FPBits; - FPB bs(x); - - double ex = static_cast(bs.get_exponent()); - - // p1 is the leading 7 bits of mx, i.e. - // p1 * 2^(-7) <= m_x < (p1 + 1) * 2^(-7). - int p1 = static_cast(bs.get_mantissa() >> (FPB::FRACTION_LEN - 7)); - - // Set bs to (1 + (mx - p1*2^(-7)) - bs.set_uintval(bs.uintval() & (FPB::FRACTION_MASK >> 7)); - bs.set_biased_exponent(FPB::EXP_BIAS); - // dx = (mx - p1*2^(-7)) / (1 + p1*2^(-7)). - double dx = (bs.get_val() - 1.0) * ONE_OVER_F[p1]; - - // Minimax polynomial of log(1 + dx) generated by Sollya with: - // > P = fpminimax(log(1 + x)/x, 6, [|D...|], [0, 2^-7]); - const double COEFFS[6] = {-0x1.ffffffffffffcp-2, 0x1.5555555552ddep-2, - -0x1.ffffffefe562dp-3, 0x1.9999817d3a50fp-3, - -0x1.554317b3f67a5p-3, 0x1.1dc5c45e09c18p-3}; - double dx2 = dx * dx; - double c1 = fputil::multiply_add(dx, COEFFS[1], COEFFS[0]); - double c2 = fputil::multiply_add(dx, COEFFS[3], COEFFS[2]); - double c3 = fputil::multiply_add(dx, COEFFS[5], COEFFS[4]); - - double p = fputil::polyeval(dx2, dx, c1, c2, c3); - double result = - fputil::multiply_add(ex, /*log(2)*/ 0x1.62e42fefa39efp-1, LOG_F[p1] + p); - return result; -} - } // namespace LIBC_NAMESPACE_DECL #endif // LLVM_LIBC_SRC_MATH_GENERIC_EXPLOGXF_H diff --git a/libc/src/math/generic/expxf16.h b/libc/src/math/generic/expxf16.h index 05ac95d586823..b17b14fa2d756 100644 --- a/libc/src/math/generic/expxf16.h +++ b/libc/src/math/generic/expxf16.h @@ -17,18 +17,11 @@ #include "src/__support/macros/config.h" #include +#include "src/__support/math/exp10_float16_constants.h" #include "src/__support/math/expf16_utils.h" namespace LIBC_NAMESPACE_DECL { -// Generated by Sollya with the following commands: -// > display = hexadecimal; -// > for i from 0 to 7 do printsingle(round(2^(i * 2^-3), SG, RN)); -constexpr cpp::array EXP2_MID_BITS = { - 0x3f80'0000U, 0x3f8b'95c2U, 0x3f98'37f0U, 0x3fa5'fed7U, - 0x3fb5'04f3U, 0x3fc5'672aU, 0x3fd7'44fdU, 0x3fea'c0c7U, -}; - LIBC_INLINE ExpRangeReduction exp2_range_reduction(float16 x) { // For -25 < x < 16, to compute 2^x, we perform the following range reduction: // find hi, mid, lo, such that: @@ -66,53 +59,6 @@ LIBC_INLINE ExpRangeReduction exp2_range_reduction(float16 x) { return {exp2_hi_mid, exp2_lo}; } -// Generated by Sollya with the following commands: -// > display = hexadecimal; -// > round(log2(10), SG, RN); -static constexpr float LOG2F_10 = 0x1.a934fp+1f; - -// Generated by Sollya with the following commands: -// > display = hexadecimal; -// > round(log10(2), SG, RN); -static constexpr float LOG10F_2 = 0x1.344136p-2f; - -LIBC_INLINE ExpRangeReduction exp10_range_reduction(float16 x) { - // For -8 < x < 5, to compute 10^x, we perform the following range reduction: - // find hi, mid, lo, such that: - // x = (hi + mid) * log2(10) + lo, in which - // hi is an integer, - // mid * 2^3 is an integer, - // -2^(-4) <= lo < 2^(-4). - // In particular, - // hi + mid = round(x * 2^3) * 2^(-3). - // Then, - // 10^x = 10^(hi + mid + lo) = 2^((hi + mid) * log2(10)) + 10^lo - // We store 2^mid in the lookup table EXP2_MID_BITS, and compute 2^hi * 2^mid - // by adding hi to the exponent field of 2^mid. 10^lo is computed using a - // degree-4 minimax polynomial generated by Sollya. - - float xf = x; - float kf = fputil::nearest_integer(xf * (LOG2F_10 * 0x1.0p+3f)); - int x_hi_mid = static_cast(kf); - unsigned x_hi = static_cast(x_hi_mid) >> 3; - unsigned x_mid = static_cast(x_hi_mid) & 0x7; - // lo = x - (hi + mid) = round(x * 2^3 * log2(10)) * log10(2) * (-2^(-3)) + x - float lo = fputil::multiply_add(kf, LOG10F_2 * -0x1.0p-3f, xf); - - uint32_t exp2_hi_mid_bits = - EXP2_MID_BITS[x_mid] + - static_cast(x_hi << fputil::FPBits::FRACTION_LEN); - float exp2_hi_mid = fputil::FPBits(exp2_hi_mid_bits).get_val(); - // Degree-4 minimax polynomial generated by Sollya with the following - // commands: - // > display = hexadecimal; - // > P = fpminimax((10^x - 1)/x, 3, [|SG...|], [-2^-4, 2^-4]); - // > 1 + x * P; - float exp10_lo = fputil::polyeval(lo, 0x1p+0f, 0x1.26bb14p+1f, 0x1.53526p+1f, - 0x1.04b434p+1f, 0x1.2bcf9ep+0f); - return {exp2_hi_mid, exp10_lo}; -} - // Generated by Sollya with the following commands: // > display = hexadecimal; // > round(log2(exp(1)), SG, RN); diff --git a/libc/src/math/generic/inv_trigf_utils.h b/libc/src/math/generic/inv_trigf_utils.h deleted file mode 100644 index 8b47aba342995..0000000000000 --- a/libc/src/math/generic/inv_trigf_utils.h +++ /dev/null @@ -1,110 +0,0 @@ -//===-- Single-precision general inverse trigonometric functions ----------===// -// -// 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_LIBC_SRC_MATH_GENERIC_INV_TRIGF_UTILS_H -#define LLVM_LIBC_SRC_MATH_GENERIC_INV_TRIGF_UTILS_H - -#include "src/__support/FPUtil/PolyEval.h" -#include "src/__support/FPUtil/multiply_add.h" -#include "src/__support/common.h" -#include "src/__support/macros/config.h" - -namespace LIBC_NAMESPACE_DECL { - -// PI and PI / 2 -static constexpr double M_MATH_PI = 0x1.921fb54442d18p+1; -static constexpr double M_MATH_PI_2 = 0x1.921fb54442d18p+0; - -extern double ATAN_COEFFS[17][9]; - -// Look-up table for atan(k/16) with k = 0..16. -static constexpr double ATAN_K_OVER_16[17] = { - 0.0, - 0x1.ff55bb72cfdeap-5, - 0x1.fd5ba9aac2f6ep-4, - 0x1.7b97b4bce5b02p-3, - 0x1.f5b75f92c80ddp-3, - 0x1.362773707ebccp-2, - 0x1.6f61941e4def1p-2, - 0x1.a64eec3cc23fdp-2, - 0x1.dac670561bb4fp-2, - 0x1.0657e94db30dp-1, - 0x1.1e00babdefeb4p-1, - 0x1.345f01cce37bbp-1, - 0x1.4978fa3269ee1p-1, - 0x1.5d58987169b18p-1, - 0x1.700a7c5784634p-1, - 0x1.819d0b7158a4dp-1, - 0x1.921fb54442d18p-1, -}; - -// For |x| <= 1/32 and 0 <= i <= 16, return Q(x) such that: -// Q(x) ~ (atan(x + i/16) - atan(i/16)) / x. -LIBC_INLINE static double atan_eval(double x, unsigned i) { - double x2 = x * x; - - double c0 = fputil::multiply_add(x, ATAN_COEFFS[i][2], ATAN_COEFFS[i][1]); - double c1 = fputil::multiply_add(x, ATAN_COEFFS[i][4], ATAN_COEFFS[i][3]); - double c2 = fputil::multiply_add(x, ATAN_COEFFS[i][6], ATAN_COEFFS[i][5]); - double c3 = fputil::multiply_add(x, ATAN_COEFFS[i][8], ATAN_COEFFS[i][7]); - - double x4 = x2 * x2; - double d1 = fputil::multiply_add(x2, c1, c0); - double d2 = fputil::multiply_add(x2, c3, c2); - double p = fputil::multiply_add(x4, d2, d1); - return p; -} - -// Evaluate atan without big lookup table. -// atan(n/d) - atan(k/16) = atan((n/d - k/16) / (1 + (n/d) * (k/16))) -// = atan((n - d * k/16)) / (d + n * k/16)) -// So we let q = (n - d * k/16) / (d + n * k/16), -// and approximate with Taylor polynomial: -// atan(q) ~ q - q^3/3 + q^5/5 - q^7/7 + q^9/9 -LIBC_INLINE static double atan_eval_no_table(double num, double den, - double k_over_16) { - double num_r = fputil::multiply_add(den, -k_over_16, num); - double den_r = fputil::multiply_add(num, k_over_16, den); - double q = num_r / den_r; - - constexpr double ATAN_TAYLOR[] = { - -0x1.5555555555555p-2, - 0x1.999999999999ap-3, - -0x1.2492492492492p-3, - 0x1.c71c71c71c71cp-4, - }; - double q2 = q * q; - double q3 = q2 * q; - double q4 = q2 * q2; - double c0 = fputil::multiply_add(q2, ATAN_TAYLOR[1], ATAN_TAYLOR[0]); - double c1 = fputil::multiply_add(q2, ATAN_TAYLOR[3], ATAN_TAYLOR[2]); - double d = fputil::multiply_add(q4, c1, c0); - return fputil::multiply_add(q3, d, q); -} - -// > Q = fpminimax(asin(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20|], -// [|1, D...|], [0, 0.5]); -static constexpr double ASIN_COEFFS[10] = { - 0x1.5555555540fa1p-3, 0x1.333333512edc2p-4, 0x1.6db6cc1541b31p-5, - 0x1.f1caff324770ep-6, 0x1.6e43899f5f4f4p-6, 0x1.1f847cf652577p-6, - 0x1.9b60f47f87146p-7, 0x1.259e2634c494fp-6, -0x1.df946fa875ddp-8, - 0x1.02311ecf99c28p-5}; - -// Evaluate P(x^2) - 1, where P(x^2) ~ asin(x)/x -LIBC_INLINE static double asin_eval(double xsq) { - double x4 = xsq * xsq; - double r1 = fputil::polyeval(x4, ASIN_COEFFS[0], ASIN_COEFFS[2], - ASIN_COEFFS[4], ASIN_COEFFS[6], ASIN_COEFFS[8]); - double r2 = fputil::polyeval(x4, ASIN_COEFFS[1], ASIN_COEFFS[3], - ASIN_COEFFS[5], ASIN_COEFFS[7], ASIN_COEFFS[9]); - return fputil::multiply_add(xsq, r2, r1); -} - -} // namespace LIBC_NAMESPACE_DECL - -#endif // LLVM_LIBC_SRC_MATH_GENERIC_INV_TRIGF_UTILS_H diff --git a/libc/src/math/generic/log1pf.cpp b/libc/src/math/generic/log1pf.cpp index 7f614293029de..16b1b34a6c944 100644 --- a/libc/src/math/generic/log1pf.cpp +++ b/libc/src/math/generic/log1pf.cpp @@ -37,6 +37,7 @@ namespace internal { // We don't need to treat denormal and 0 LIBC_INLINE float log(double x) { + using namespace acoshf_internal; constexpr double LOG_2 = 0x1.62e42fefa39efp-1; using FPBits = typename fputil::FPBits; diff --git a/libc/src/math/generic/powf.cpp b/libc/src/math/generic/powf.cpp index dfdfd5d6d5760..a45ef511c9bad 100644 --- a/libc/src/math/generic/powf.cpp +++ b/libc/src/math/generic/powf.cpp @@ -9,20 +9,17 @@ #include "src/math/powf.h" #include "common_constants.h" // Lookup tables EXP_M1 and EXP_M2. #include "src/__support/CPP/bit.h" -#include "src/__support/CPP/optional.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/PolyEval.h" #include "src/__support/FPUtil/double_double.h" -#include "src/__support/FPUtil/except_value_utils.h" #include "src/__support/FPUtil/multiply_add.h" #include "src/__support/FPUtil/nearest_integer.h" -#include "src/__support/FPUtil/rounding_mode.h" #include "src/__support/FPUtil/sqrt.h" // Speedup for powf(x, 1/2) = sqrtf(x) #include "src/__support/common.h" #include "src/__support/macros/config.h" #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY +#include "src/__support/math/exp10f.h" // Speedup for powf(10, y) = exp10f(y) -#include "exp10f_impl.h" // Speedup for powf(10, y) = exp10f(y) #include "exp2f_impl.h" // Speedup for powf(2, y) = exp2f(y) namespace LIBC_NAMESPACE_DECL { @@ -781,7 +778,7 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) { return generic::exp2f(y); case 0x4120'0000: // x = 10.0f // pow(10, y) = exp10(y) - return generic::exp10f(y); + return math::exp10f(y); #endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS } diff --git a/libc/src/math/generic/sinhf.cpp b/libc/src/math/generic/sinhf.cpp index d6158fd302536..63111f84de141 100644 --- a/libc/src/math/generic/sinhf.cpp +++ b/libc/src/math/generic/sinhf.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "src/math/sinhf.h" +#include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/rounding_mode.h" #include "src/__support/macros/config.h" diff --git a/libc/src/string/memory_utils/CMakeLists.txt b/libc/src/string/memory_utils/CMakeLists.txt index 633d9f12949d2..8ab1c9ff98d2f 100644 --- a/libc/src/string/memory_utils/CMakeLists.txt +++ b/libc/src/string/memory_utils/CMakeLists.txt @@ -9,6 +9,7 @@ add_header_library( aarch64/inline_memset.h arm/common.h arm/inline_memcpy.h + arm/inline_memset.h generic/aligned_access.h generic/byte_per_byte.h inline_bcmp.h diff --git a/libc/src/string/memory_utils/arm/common.h b/libc/src/string/memory_utils/arm/common.h index 155bc3481709e..b9f40b64fed98 100644 --- a/libc/src/string/memory_utils/arm/common.h +++ b/libc/src/string/memory_utils/arm/common.h @@ -14,6 +14,9 @@ #include // size_t +// Our minimum supported compiler version does not recognize the standard +// [[likely]] / [[unlikely]] attributes so we use the preprocessor. + // https://libc.llvm.org/compiler_support.html // Support for [[likely]] / [[unlikely]] // [X] GCC 12.2 diff --git a/libc/src/string/memory_utils/arm/inline_memcpy.h b/libc/src/string/memory_utils/arm/inline_memcpy.h index 30b99d41e0967..c748048a3e586 100644 --- a/libc/src/string/memory_utils/arm/inline_memcpy.h +++ b/libc/src/string/memory_utils/arm/inline_memcpy.h @@ -13,6 +13,7 @@ #ifndef LLVM_LIBC_SRC_STRING_MEMORY_UTILS_ARM_INLINE_MEMCPY_H #define LLVM_LIBC_SRC_STRING_MEMORY_UTILS_ARM_INLINE_MEMCPY_H +#include "src/__support/CPP/type_traits.h" // always_false #include "src/__support/macros/attributes.h" // LIBC_INLINE #include "src/__support/macros/optimization.h" // LIBC_LOOP_NOUNROLL #include "src/string/memory_utils/arm/common.h" // LIBC_ATTR_LIKELY, LIBC_ATTR_UNLIKELY @@ -36,7 +37,7 @@ LIBC_INLINE void copy(void *dst, const void *src) { } else if constexpr (access == AssumeAccess::kUnknown) { memcpy_inline(dst, src); } else { - static_assert(false); + static_assert(cpp::always_false, "Invalid AssumeAccess"); } } @@ -54,7 +55,7 @@ LIBC_INLINE void copy_block_and_bump_pointers(Ptr &dst, CPtr &src) { copy(dst + offset, src + offset); } } else { - static_assert(false, "Invalid BlockOp"); + static_assert(cpp::always_false, "Invalid BlockOp"); } // In the 1, 2, 4 byte copy case, the compiler can fold pointer offsetting // into the load/store instructions. @@ -102,6 +103,7 @@ copy_bytes_and_bump_pointers(Ptr &dst, CPtr &src, size_t size) { copy_bytes_and_bump_pointers(dst, src, offset); size -= offset; } + constexpr AssumeAccess kAligned = AssumeAccess::kAligned; const auto src_alignment = distance_to_align_down(src); if (src_alignment == 0) LIBC_ATTR_LIKELY { @@ -110,14 +112,11 @@ copy_bytes_and_bump_pointers(Ptr &dst, CPtr &src, size_t size) { // load/store multiple (LDM, STM), each of 4 words. This requires more // registers so additional push/pop are needed but the speedup is worth // it. - consume_by_block<64, BlockOp::kFull, AssumeAccess::kAligned>(dst, src, - size); + consume_by_block<64, BlockOp::kFull, kAligned>(dst, src, size); // Then we use blocks of 4 word load/store. - consume_by_block<16, BlockOp::kByWord, AssumeAccess::kAligned>(dst, src, - size); + consume_by_block<16, BlockOp::kByWord, kAligned>(dst, src, size); // Then we use word by word copy. - consume_by_block<4, BlockOp::kByWord, AssumeAccess::kAligned>(dst, src, - size); + consume_by_block<4, BlockOp::kByWord, kAligned>(dst, src, size); } else { // `dst` is aligned but `src` is not. @@ -128,7 +127,7 @@ copy_bytes_and_bump_pointers(Ptr &dst, CPtr &src, size_t size) { src_alignment == 2 ? load_aligned(src) : load_aligned(src); - copy(dst, &value); + copy(dst, &value); dst += kWordSize; src += kWordSize; size -= kWordSize; @@ -173,7 +172,7 @@ copy_bytes_and_bump_pointers(Ptr &dst, CPtr &src, size_t size) { // accesses through the use of load/store multiple (LDM, STM) and load/store // double (LDRD, STRD) instructions are generally not supported and can fault. // By forcing decomposition of 64 bytes copy into word by word copy, the - // compiler can use the first load to prefetch memory: + // compiler uses a load to prefetch the next cache line: // ldr r3, [r1, #64]! <- prefetch next cache line // str r3, [r0] // ldr r3, [r1, #0x4] @@ -183,11 +182,10 @@ copy_bytes_and_bump_pointers(Ptr &dst, CPtr &src, size_t size) { // str r3, [r0, #0x3c] // This is a bit detrimental for sizes between 64 and 256 (less than 10% // penalty) but the prefetch yields better throughput for larger copies. - consume_by_block<64, BlockOp::kByWord, AssumeAccess::kUnknown>(dst, src, - size); - consume_by_block<16, BlockOp::kByWord, AssumeAccess::kUnknown>(dst, src, - size); - consume_by_block<4, BlockOp::kByWord, AssumeAccess::kUnknown>(dst, src, size); + constexpr AssumeAccess kUnknown = AssumeAccess::kUnknown; + consume_by_block<64, BlockOp::kByWord, kUnknown>(dst, src, size); + consume_by_block<16, BlockOp::kByWord, kUnknown>(dst, src, size); + consume_by_block<4, BlockOp::kByWord, kUnknown>(dst, src, size); if (size & 1) copy_block_and_bump_pointers<1>(dst, src); if (size & 2) diff --git a/libc/src/string/memory_utils/arm/inline_memset.h b/libc/src/string/memory_utils/arm/inline_memset.h new file mode 100644 index 0000000000000..a7ef9cc7df916 --- /dev/null +++ b/libc/src/string/memory_utils/arm/inline_memset.h @@ -0,0 +1,156 @@ +//===-- Memset implementation for arm ---------------------------*- 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 +// +//===----------------------------------------------------------------------===// +// The functions defined in this file give approximate code size. These sizes +// assume the following configuration options: +// - LIBC_CONF_KEEP_FRAME_POINTER = false +// - LIBC_CONF_ENABLE_STRONG_STACK_PROTECTOR = false +// - LIBC_ADD_NULL_CHECKS = false +#ifndef LLVM_LIBC_SRC_STRING_MEMORY_UTILS_ARM_INLINE_MEMSET_H +#define LLVM_LIBC_SRC_STRING_MEMORY_UTILS_ARM_INLINE_MEMSET_H + +#include "src/__support/CPP/type_traits.h" // always_false +#include "src/__support/macros/attributes.h" // LIBC_INLINE +#include "src/__support/macros/optimization.h" // LIBC_LOOP_NOUNROLL +#include "src/string/memory_utils/arm/common.h" // LIBC_ATTR_LIKELY, LIBC_ATTR_UNLIKELY +#include "src/string/memory_utils/utils.h" // memcpy_inline, distance_to_align + +#include // size_t + +namespace LIBC_NAMESPACE_DECL { + +namespace { + +template +LIBC_INLINE void set(void *dst, uint32_t value) { + static_assert(bytes == 1 || bytes == 2 || bytes == 4); + if constexpr (access == AssumeAccess::kAligned) { + constexpr size_t alignment = bytes > kWordSize ? kWordSize : bytes; + memcpy_inline(assume_aligned(dst), &value); + } else if constexpr (access == AssumeAccess::kUnknown) { + memcpy_inline(dst, &value); + } else { + static_assert(cpp::always_false, "Invalid AssumeAccess"); + } +} + +template +LIBC_INLINE void set_block_and_bump_pointers(Ptr &dst, uint32_t value) { + if constexpr (bytes <= kWordSize) { + set(dst, value); + } else { + static_assert(bytes % kWordSize == 0 && bytes >= kWordSize); + LIBC_LOOP_UNROLL + for (size_t offset = 0; offset < bytes; offset += kWordSize) { + set(dst + offset, value); + } + } + // In the 1, 2, 4 byte set case, the compiler can fold pointer offsetting + // into the store instructions. + // e.g., + // strb r3, [r0], #1 + dst += bytes; +} + +template +LIBC_INLINE void consume_by_block(Ptr &dst, uint32_t value, size_t &size) { + LIBC_LOOP_NOUNROLL + for (size_t i = 0; i < size / bytes; ++i) + set_block_and_bump_pointers(dst, value); + size %= bytes; +} + +[[maybe_unused]] LIBC_INLINE void +set_bytes_and_bump_pointers(Ptr &dst, uint32_t value, size_t size) { + LIBC_LOOP_NOUNROLL + for (size_t i = 0; i < size; ++i) { + set<1, AssumeAccess::kUnknown>(dst++, value); + } +} + +} // namespace + +// Implementation for Cortex-M0, M0+, M1. It compiles down to 140 bytes when +// used through `memset` that also needs to return the `dst` ptr. These cores do +// not allow unaligned stores so all accesses are aligned. +[[maybe_unused]] LIBC_INLINE void +inline_memset_arm_low_end(Ptr dst, uint8_t value, size_t size) { + if (size >= 8) + LIBC_ATTR_LIKELY { + // Align `dst` to word boundary. + if (const size_t offset = distance_to_align_up(dst)) + LIBC_ATTR_UNLIKELY { + set_bytes_and_bump_pointers(dst, value, offset); + size -= offset; + } + const uint32_t value32 = value * 0x01010101U; // splat value in each byte + consume_by_block<64, AssumeAccess::kAligned>(dst, value32, size); + consume_by_block<16, AssumeAccess::kAligned>(dst, value32, size); + consume_by_block<4, AssumeAccess::kAligned>(dst, value32, size); + } + set_bytes_and_bump_pointers(dst, value, size); +} + +// Implementation for Cortex-M3, M4, M7, M23, M33, M35P, M52 with hardware +// support for unaligned loads and stores. It compiles down to 186 bytes when +// used through `memset` that also needs to return the `dst` ptr. +[[maybe_unused]] LIBC_INLINE void +inline_memset_arm_mid_end(Ptr dst, uint8_t value, size_t size) { + const uint32_t value32 = value * 0x01010101U; // splat value in each byte + if (misaligned(dst)) + LIBC_ATTR_UNLIKELY { + if (size < 8) + LIBC_ATTR_UNLIKELY { + if (size & 1) + set_block_and_bump_pointers<1>(dst, value32); + if (size & 2) + set_block_and_bump_pointers<2>(dst, value32); + if (size & 4) + set_block_and_bump_pointers<4>(dst, value32); + return; + } + const size_t offset = distance_to_align_up(dst); + if (offset & 1) + set_block_and_bump_pointers<1>(dst, value32); + if (offset & 2) + set_block_and_bump_pointers<2>(dst, value32); + size -= offset; + } + // If we tell the compiler that the stores are aligned it will generate 8 x + // STRD instructions. By not specifying alignment, the compiler conservatively + // uses 16 x STR.W and is able to use the first one to prefetch the + // destination in advance leading to better asymptotic performances. + // str r12, [r3, #64]! <- prefetch next cache line + // str.w r12, [r3, #0x4] + // str.w r12, [r3, #0x8] + // ... + // str.w r12, [r3, #0x38] + // str.w r12, [r3, #0x3c] + consume_by_block<64, AssumeAccess::kUnknown>(dst, value32, size); + // Prefetching does not matter anymore at this scale so using STRD yields + // better results. + consume_by_block<16, AssumeAccess::kAligned>(dst, value32, size); + consume_by_block<4, AssumeAccess::kAligned>(dst, value32, size); + if (size & 1) + set_block_and_bump_pointers<1>(dst, value32); + if (size & 2) + LIBC_ATTR_UNLIKELY + set_block_and_bump_pointers<2>(dst, value32); +} + +[[maybe_unused]] LIBC_INLINE void +inline_memset_arm_dispatch(Ptr dst, uint8_t value, size_t size) { +#ifdef __ARM_FEATURE_UNALIGNED + return inline_memset_arm_mid_end(dst, value, size); +#else + return inline_memset_arm_low_end(dst, value, size); +#endif +} + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_STRING_MEMORY_UTILS_ARM_INLINE_MEMCPY_H diff --git a/libc/src/string/memory_utils/inline_memset.h b/libc/src/string/memory_utils/inline_memset.h index fd9c29ea4410a..e41bdb626d60e 100644 --- a/libc/src/string/memory_utils/inline_memset.h +++ b/libc/src/string/memory_utils/inline_memset.h @@ -18,6 +18,9 @@ #if defined(LIBC_TARGET_ARCH_IS_X86) #include "src/string/memory_utils/x86_64/inline_memset.h" #define LIBC_SRC_STRING_MEMORY_UTILS_MEMSET inline_memset_x86 +#elif defined(LIBC_TARGET_ARCH_IS_ARM) +#include "src/string/memory_utils/arm/inline_memset.h" +#define LIBC_SRC_STRING_MEMORY_UTILS_MEMSET inline_memset_arm_dispatch #elif defined(LIBC_TARGET_ARCH_IS_AARCH64) #include "src/string/memory_utils/aarch64/inline_memset.h" #define LIBC_SRC_STRING_MEMORY_UTILS_MEMSET inline_memset_aarch64_dispatch @@ -34,7 +37,8 @@ namespace LIBC_NAMESPACE_DECL { -LIBC_INLINE static void inline_memset(void *dst, uint8_t value, size_t count) { +[[gnu::flatten]] LIBC_INLINE void inline_memset(void *dst, uint8_t value, + size_t count) { LIBC_SRC_STRING_MEMORY_UTILS_MEMSET(reinterpret_cast(dst), value, count); } diff --git a/libc/src/string/string_utils.h b/libc/src/string/string_utils.h index 4f56263fce8ec..1231117586a7c 100644 --- a/libc/src/string/string_utils.h +++ b/libc/src/string/string_utils.h @@ -21,6 +21,8 @@ #include "src/__support/macros/config.h" #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY +#include // uintptr_t + namespace LIBC_NAMESPACE_DECL { namespace internal { diff --git a/libc/src/sys/epoll/linux/epoll_create.cpp b/libc/src/sys/epoll/linux/epoll_create.cpp index 2e44e883ddf0a..dcd082b56f9ad 100644 --- a/libc/src/sys/epoll/linux/epoll_create.cpp +++ b/libc/src/sys/epoll/linux/epoll_create.cpp @@ -20,6 +20,11 @@ LLVM_LIBC_FUNCTION(int, epoll_create, ([[maybe_unused]] int size)) { #ifdef SYS_epoll_create int ret = LIBC_NAMESPACE::syscall_impl(SYS_epoll_create, size); #elif defined(SYS_epoll_create1) + if (size == 0) { + libc_errno = EINVAL; + return -1; + } + int ret = LIBC_NAMESPACE::syscall_impl(SYS_epoll_create1, 0); #else #error \ diff --git a/libc/src/sys/time/linux/setitimer.cpp b/libc/src/sys/time/linux/setitimer.cpp index 1de0d43297760..fb163586e30d9 100644 --- a/libc/src/sys/time/linux/setitimer.cpp +++ b/libc/src/sys/time/linux/setitimer.cpp @@ -22,9 +22,9 @@ LLVM_LIBC_FUNCTION(int, setitimer, // There is no SYS_setitimer_time64 call, so we can't use time_t directly, // and need to convert it to long first. long new_value32[4] = {static_cast(new_value->it_interval.tv_sec), - new_value->it_interval.tv_usec, + static_cast(new_value->it_interval.tv_usec), static_cast(new_value->it_value.tv_sec), - new_value->it_value.tv_usec}; + static_cast(new_value->it_value.tv_usec)}; long old_value32[4]; ret = LIBC_NAMESPACE::syscall_impl(SYS_setitimer, which, new_value32, diff --git a/libc/src/sys/time/linux/utimes.cpp b/libc/src/sys/time/linux/utimes.cpp index ed37b42aedf6c..9c00ce9909f2f 100644 --- a/libc/src/sys/time/linux/utimes.cpp +++ b/libc/src/sys/time/linux/utimes.cpp @@ -59,8 +59,10 @@ LLVM_LIBC_FUNCTION(int, utimes, ts[1].tv_sec = times[1].tv_sec; // convert u-seconds to nanoseconds - ts[0].tv_nsec = times[0].tv_usec * 1000; - ts[1].tv_nsec = times[1].tv_usec * 1000; + ts[0].tv_nsec = + static_cast(times[0].tv_usec * 1000); + ts[1].tv_nsec = + static_cast(times[1].tv_usec * 1000); ts_ptr = ts; } diff --git a/libc/src/wchar/CMakeLists.txt b/libc/src/wchar/CMakeLists.txt index 7ace1a6ca66ba..159778df6acca 100644 --- a/libc/src/wchar/CMakeLists.txt +++ b/libc/src/wchar/CMakeLists.txt @@ -1,3 +1,13 @@ +add_header_library( + wchar_utils + HDRS + wchar_utils.h + DEPENDS + libc.hdr.types.size_t + libc.hdr.types.wchar_t + libc.src.__support.common +) + add_entrypoint_object( wcslen SRCS @@ -255,6 +265,8 @@ add_entrypoint_object( DEPENDS libc.hdr.wchar_macros libc.hdr.types.size_t + libc.src.wchar.wchar_utils + libc.src.__support.macros.null_check ) add_entrypoint_object( @@ -266,6 +278,8 @@ add_entrypoint_object( DEPENDS libc.hdr.wchar_macros libc.hdr.types.size_t + libc.src.wchar.wchar_utils + libc.src.__support.macros.null_check ) add_entrypoint_object( diff --git a/libc/src/wchar/mbtowc.cpp b/libc/src/wchar/mbtowc.cpp index eae39ba6081f3..6d099d43da5fa 100644 --- a/libc/src/wchar/mbtowc.cpp +++ b/libc/src/wchar/mbtowc.cpp @@ -25,10 +25,7 @@ LLVM_LIBC_FUNCTION(int, mbtowc, if (s == nullptr) return 0; internal::mbstate internal_mbstate; - // temp ptr to use if pwc is nullptr - wchar_t buf[1]; - auto ret = - internal::mbrtowc(pwc == nullptr ? buf : pwc, s, n, &internal_mbstate); + auto ret = internal::mbrtowc(pwc, s, n, &internal_mbstate); if (!ret.has_value() || static_cast(ret.value()) == -2) { // Encoding failure libc_errno = EILSEQ; diff --git a/libc/src/wchar/wchar_utils.h b/libc/src/wchar/wchar_utils.h new file mode 100644 index 0000000000000..e0218c7d89b1f --- /dev/null +++ b/libc/src/wchar/wchar_utils.h @@ -0,0 +1,45 @@ +//===-- wchar utils ---------------------------------------------*- 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_LIBC_SRC_WCHAR_WCHAR_UTILS_H +#define LLVM_LIBC_SRC_WCHAR_WCHAR_UTILS_H + +#include "hdr/types/size_t.h" +#include "hdr/types/wchar_t.h" +#include "src/__support/common.h" +#include "src/__support/macros/attributes.h" // LIBC_INLINE + +namespace LIBC_NAMESPACE_DECL { +namespace internal { + +// returns true if the character exists in the string +LIBC_INLINE static bool wcschr(wchar_t c, const wchar_t *str) { + for (int n = 0; str[n]; ++n) { + if (str[n] == c) + return true; + } + return false; +} + +// bool should be true for wcscspn for complimentary span +// should be false for wcsspn since we want it to span +LIBC_INLINE static size_t wcsspn(const wchar_t *s1, const wchar_t *s2, + bool not_match_set) { + size_t i = 0; + for (; s1[i]; ++i) { + bool in_set = wcschr(s1[i], s2); + if (in_set == not_match_set) + return i; + } + return i; +} + +} // namespace internal +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_WCHAR_WCHAR_UTILS_H diff --git a/libc/src/wchar/wcscspn.cpp b/libc/src/wchar/wcscspn.cpp index 8869d84cdfdee..34f3451b19c30 100644 --- a/libc/src/wchar/wcscspn.cpp +++ b/libc/src/wchar/wcscspn.cpp @@ -12,23 +12,15 @@ #include "hdr/types/wchar_t.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" +#include "src/__support/macros/null_check.h" +#include "wchar_utils.h" namespace LIBC_NAMESPACE_DECL { -bool check(wchar_t c, const wchar_t *s2) { - for (int n = 0; s2[n]; ++n) { - if (s2[n] == c) - return false; - } - return true; -} LLVM_LIBC_FUNCTION(size_t, wcscspn, (const wchar_t *s1, const wchar_t *s2)) { - size_t i = 0; - for (; s1[i]; ++i) { - if (!check(s1[i], s2)) - return i; - } - return i; + LIBC_CRASH_ON_NULLPTR(s1); + LIBC_CRASH_ON_NULLPTR(s2); + return internal::wcsspn(s1, s2, /*not_match_set=*/true); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/wchar/wcsspn.cpp b/libc/src/wchar/wcsspn.cpp index 23de381a2d954..ae2cf5a41ae41 100644 --- a/libc/src/wchar/wcsspn.cpp +++ b/libc/src/wchar/wcsspn.cpp @@ -12,23 +12,15 @@ #include "hdr/types/wchar_t.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" +#include "src/__support/macros/null_check.h" +#include "wchar_utils.h" namespace LIBC_NAMESPACE_DECL { -bool check(wchar_t c, const wchar_t *s2) { - for (int n = 0; s2[n]; ++n) { - if (s2[n] == c) - return true; - } - return false; -} LLVM_LIBC_FUNCTION(size_t, wcsspn, (const wchar_t *s1, const wchar_t *s2)) { - size_t i = 0; - for (; s1[i]; ++i) { - if (!check(s1[i], s2)) - return i; - } - return i; + LIBC_CRASH_ON_NULLPTR(s1); + LIBC_CRASH_ON_NULLPTR(s2); + return internal::wcsspn(s1, s2, /*not_match_set=*/false); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/wctype/CMakeLists.txt b/libc/src/wctype/CMakeLists.txt new file mode 100644 index 0000000000000..3ac5eaef8ed8b --- /dev/null +++ b/libc/src/wctype/CMakeLists.txt @@ -0,0 +1,9 @@ +add_entrypoint_object( + iswalpha + SRCS + iswalpha.cpp + HDRS + iswalpha.h + DEPENDS + libc.src.__support.wctype_utils +) diff --git a/libc/src/wctype/iswalpha.cpp b/libc/src/wctype/iswalpha.cpp new file mode 100644 index 0000000000000..e18f29370fbd0 --- /dev/null +++ b/libc/src/wctype/iswalpha.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of iswalpha ----------------------------------------===// +// +// 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 "src/wctype/iswalpha.h" +#include "src/__support/common.h" +#include "src/__support/wctype_utils.h" + +#include "hdr/types/wint_t.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(bool, iswalpha, (wint_t c)) { return internal::iswalpha(c); } + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/wctype/iswalpha.h b/libc/src/wctype/iswalpha.h new file mode 100644 index 0000000000000..681fc6ba79a54 --- /dev/null +++ b/libc/src/wctype/iswalpha.h @@ -0,0 +1,21 @@ +//===-- Implementation header for iswalpha ----------------------*- 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_LIBC_SRC_WCTYPE_ISWALPHA_H +#define LLVM_LIBC_SRC_WCTYPE_ISWALPHA_H + +#include "hdr/types/wint_t.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE_DECL { + +bool iswalpha(wint_t c); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_WCTYPE_ISWALPHA_H diff --git a/libc/test/CMakeLists.txt b/libc/test/CMakeLists.txt index 1a0780faff512..011ad6aeb34b7 100644 --- a/libc/test/CMakeLists.txt +++ b/libc/test/CMakeLists.txt @@ -20,6 +20,7 @@ endif() add_subdirectory(src) add_subdirectory(utils) +add_subdirectory(shared) if(NOT LLVM_LIBC_FULL_BUILD) return() diff --git a/libc/test/UnitTest/Test.h b/libc/test/UnitTest/Test.h index a5a2a3c7cf58e..e70fc51869624 100644 --- a/libc/test/UnitTest/Test.h +++ b/libc/test/UnitTest/Test.h @@ -52,4 +52,13 @@ libc_errno = 0; \ } while (0) +// Some macro utility to append file names with LIBC_TEST macro's value to be +// used in stdio tests. +#undef STR +#undef EVAL_THEN_STR +#define STR(X) #X +#define EVAL_THEN_STR(X) STR(X) + +#define APPEND_LIBC_TEST(X) X "." EVAL_THEN_STR(LIBC_TEST) + #endif // LLVM_LIBC_TEST_UNITTEST_TEST_H diff --git a/libc/test/include/CMakeLists.txt b/libc/test/include/CMakeLists.txt index 24935cec048ba..11e4c3a84157f 100644 --- a/libc/test/include/CMakeLists.txt +++ b/libc/test/include/CMakeLists.txt @@ -484,6 +484,21 @@ add_libc_test( libc.include.llvm-libc-macros.math_function_macros ) +add_libc_test( + math_constants_c_test + C_TEST + UNIT_TEST_ONLY + SUITE + libc_include_tests + SRCS + math_constants_test.c + COMPILE_OPTIONS + -Wall + -Werror + DEPENDS + libc.include.llvm-libc-macros.math_macros +) + # Test `#include <...>` of each header in each available language mode. # This is gated on -DLLVM_LIBC_BUILD_HEADER_TESTS=ON until all the bugs # in headers are fixed so the tests all compile. diff --git a/libc/test/include/math_constants_test.c b/libc/test/include/math_constants_test.c new file mode 100644 index 0000000000000..eb497a9d8a50a --- /dev/null +++ b/libc/test/include/math_constants_test.c @@ -0,0 +1,23 @@ +//===-- Unittests for math constants --------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" + +#define IS_DOUBLE(X) _Generic((X), double: 1, default: 0) + +#define IS_FLOAT(X) _Generic((X), float: 1, default: 0) + +// check if macro is defined +#ifndef M_PI +#error "M_PI macro is not defined" +#else +int main(void) { + _Static_assert(IS_DOUBLE(M_PI), "M_PI is not of double type."); + _Static_assert(IS_FLOAT(M_PIf), "M_PIf is not of float type."); + return 0; +} +#endif diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt new file mode 100644 index 0000000000000..89b607d7e5cc3 --- /dev/null +++ b/libc/test/shared/CMakeLists.txt @@ -0,0 +1,28 @@ +add_custom_target(libc-shared-tests) + +add_fp_unittest( + shared_math_test + SUITE + libc-shared-tests + SRCS + shared_math_test.cpp + DEPENDS + libc.src.__support.math.acos + libc.src.__support.math.acosf + libc.src.__support.math.acosf16 + libc.src.__support.math.acoshf + libc.src.__support.math.acoshf16 + libc.src.__support.math.erff + libc.src.__support.math.exp + libc.src.__support.math.exp10 + libc.src.__support.math.exp10f + libc.src.__support.math.exp10f16 + libc.src.__support.math.expf + libc.src.__support.math.expf16 + libc.src.__support.math.frexpf + libc.src.__support.math.frexpf128 + libc.src.__support.math.frexpf16 + libc.src.__support.math.ldexpf + libc.src.__support.math.ldexpf128 + libc.src.__support.math.ldexpf16 +) diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp new file mode 100644 index 0000000000000..8d3cebdf0745c --- /dev/null +++ b/libc/test/shared/shared_math_test.cpp @@ -0,0 +1,71 @@ +//===-- Unittests for shared math functions -------------------------------===// +// +// 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 "shared/math.h" +#include "test/UnitTest/FPMatcher.h" + +#ifdef LIBC_TYPES_HAS_FLOAT16 + +TEST(LlvmLibcSharedMathTest, AllFloat16) { + int exponent; + + EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::acoshf16(1.0f)); + + EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::exp10f16(0.0f16)); + + EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::expf16(0.0f16)); + + ASSERT_FP_EQ(float16(8 << 5), LIBC_NAMESPACE::shared::ldexpf16(float(8), 5)); + ASSERT_FP_EQ(float16(-1 * (8 << 5)), + LIBC_NAMESPACE::shared::ldexpf16(float(-8), 5)); + + EXPECT_FP_EQ_ALL_ROUNDING(0.75f16, + LIBC_NAMESPACE::shared::frexpf16(24.0f, &exponent)); + EXPECT_EQ(exponent, 5); + + EXPECT_FP_EQ(0x1.921fb6p+0f16, LIBC_NAMESPACE::shared::acosf16(0.0f16)); +} + +#endif + +TEST(LlvmLibcSharedMathTest, AllFloat) { + int exponent; + + EXPECT_FP_EQ(0x1.921fb6p+0, LIBC_NAMESPACE::shared::acosf(0.0f)); + EXPECT_FP_EQ(0x1p+0f, LIBC_NAMESPACE::shared::exp10f(0.0f)); + EXPECT_FP_EQ(0x1p+0f, LIBC_NAMESPACE::shared::expf(0.0f)); + EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::erff(0.0f)); + EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::acoshf(1.0f)); + + EXPECT_FP_EQ_ALL_ROUNDING(0.75f, + LIBC_NAMESPACE::shared::frexpf(24.0f, &exponent)); + EXPECT_EQ(exponent, 5); + + ASSERT_FP_EQ(float(8 << 5), LIBC_NAMESPACE::shared::ldexpf(float(8), 5)); + ASSERT_FP_EQ(float(-1 * (8 << 5)), + LIBC_NAMESPACE::shared::ldexpf(float(-8), 5)); +} + +TEST(LlvmLibcSharedMathTest, AllDouble) { + EXPECT_FP_EQ(0x1.921fb54442d18p+0, LIBC_NAMESPACE::shared::acos(0.0)); + EXPECT_FP_EQ(0x1p+0, LIBC_NAMESPACE::shared::exp(0.0)); + EXPECT_FP_EQ(0x1p+0, LIBC_NAMESPACE::shared::exp10(0.0)); +} + +TEST(LlvmLibcSharedMathTest, AllFloat128) { + int exponent; + + EXPECT_FP_EQ_ALL_ROUNDING( + float128(0.75), LIBC_NAMESPACE::shared::frexpf128(24.0f, &exponent)); + EXPECT_EQ(exponent, 5); + + ASSERT_FP_EQ(float128(8 << 5), + LIBC_NAMESPACE::shared::ldexpf128(float(8), 5)); + ASSERT_FP_EQ(float128(-1 * (8 << 5)), + LIBC_NAMESPACE::shared::ldexpf128(float(-8), 5)); +} diff --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt index 6dca47b5343e6..b3eba43582074 100644 --- a/libc/test/src/CMakeLists.txt +++ b/libc/test/src/CMakeLists.txt @@ -70,6 +70,7 @@ add_subdirectory(stdlib) add_subdirectory(string) add_subdirectory(strings) add_subdirectory(wchar) +add_subdirectory(wctype) add_subdirectory(time) add_subdirectory(unistd) diff --git a/libc/test/src/__support/FPUtil/CMakeLists.txt b/libc/test/src/__support/FPUtil/CMakeLists.txt index dfd90057b6ebf..81db4ccae44c6 100644 --- a/libc/test/src/__support/FPUtil/CMakeLists.txt +++ b/libc/test/src/__support/FPUtil/CMakeLists.txt @@ -39,6 +39,12 @@ add_fp_unittest( libc.src.__support.FPUtil.rounding_mode ) +# TODO: Temporally disable bfloat16 test until MPCommon target is updated +# https://github.com/llvm/llvm-project/pull/149678 +if(LLVM_LIBC_FULL_BUILD) + return() +endif() + add_fp_unittest( bfloat16_test NEED_MPFR @@ -49,3 +55,15 @@ add_fp_unittest( DEPENDS libc.src.__support.FPUtil.bfloat16 ) + +add_fp_unittest( + comparison_operations_test + SUITE + libc-fputil-tests + SRCS + comparison_operations_test.cpp + DEPENDS + libc.src.__support.FPUtil.bfloat16 + libc.src.__support.FPUtil.comparison_operations + libc.src.__support.macros.properties.types +) diff --git a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp new file mode 100644 index 0000000000000..04a3321fd5dbf --- /dev/null +++ b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp @@ -0,0 +1,350 @@ +//===-- Unittests for comparison operations on floating-point numbers -----===// +// +// 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 "src/__support/FPUtil/bfloat16.h" +#include "src/__support/FPUtil/comparison_operations.h" +#include "src/__support/macros/properties/types.h" +#include "test/UnitTest/FEnvSafeTest.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +using LIBC_NAMESPACE::fputil::equals; +using LIBC_NAMESPACE::fputil::greater_than; +using LIBC_NAMESPACE::fputil::greater_than_or_equals; +using LIBC_NAMESPACE::fputil::less_than; +using LIBC_NAMESPACE::fputil::less_than_or_equals; + +using BFloat16 = LIBC_NAMESPACE::fputil::BFloat16; + +template +class ComparisonOperationsTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { + DECLARE_SPECIAL_CONSTANTS(T) + + // TODO: Make these constexpr once quick_get_round is made constexpr. + T normal1; + T neg_normal1; + T normal2; + T small; + T neg_small; + T large; + T neg_large; + +public: + void SetUp() override { + with_fenv_preserved([this]() { + normal1 = T(3.14); + neg_normal1 = T(-3.14); + normal2 = T(2.71); + small = T(0.1); + neg_small = T(-0.1); + large = T(10000.0); + neg_large = T(-10000.0); + }); + } + + void test_equals() { + EXPECT_TRUE(equals(neg_zero, neg_zero)); + EXPECT_TRUE(equals(zero, neg_zero)); + EXPECT_TRUE(equals(neg_zero, zero)); + + EXPECT_TRUE(equals(inf, inf)); + EXPECT_TRUE(equals(neg_inf, neg_inf)); + EXPECT_FALSE(equals(inf, neg_inf)); + EXPECT_FALSE(equals(neg_inf, inf)); + + EXPECT_TRUE(equals(normal1, normal1)); + EXPECT_TRUE(equals(normal2, normal2)); + EXPECT_FALSE(equals(normal1, normal2)); + EXPECT_FALSE(equals(normal1, neg_normal1)); + + auto test_qnan = [&](T x, T y) { + LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); + EXPECT_FALSE(equals(x, y)); + EXPECT_FP_EXCEPTION(0); + }; + + test_qnan(aNaN, aNaN); + test_qnan(aNaN, neg_aNaN); + test_qnan(aNaN, zero); + test_qnan(aNaN, inf); + test_qnan(aNaN, normal1); + + test_qnan(neg_aNaN, neg_aNaN); + test_qnan(neg_aNaN, aNaN); + test_qnan(neg_aNaN, zero); + test_qnan(neg_aNaN, inf); + test_qnan(neg_aNaN, normal1); + + auto test_snan = [&](T x, T y) { + LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); + EXPECT_FALSE(equals(x, y)); + EXPECT_FP_EXCEPTION(FE_INVALID); + }; + + test_snan(sNaN, sNaN); + test_snan(sNaN, neg_sNaN); + test_snan(sNaN, aNaN); + test_snan(sNaN, neg_aNaN); + test_snan(sNaN, zero); + test_snan(sNaN, neg_zero); + test_snan(sNaN, inf); + test_snan(sNaN, neg_inf); + test_snan(sNaN, normal1); + + test_snan(neg_sNaN, neg_sNaN); + test_snan(neg_sNaN, sNaN); + test_snan(neg_sNaN, aNaN); + test_snan(neg_sNaN, neg_aNaN); + test_snan(neg_sNaN, zero); + test_snan(neg_sNaN, neg_zero); + test_snan(neg_sNaN, inf); + test_snan(neg_sNaN, neg_inf); + test_snan(neg_sNaN, normal1); + } + + void test_less_than() { + EXPECT_TRUE(less_than(neg_small, small)); + EXPECT_TRUE(less_than(small, large)); + + EXPECT_TRUE(less_than(neg_large, neg_small)); + EXPECT_FALSE(less_than(large, small)); + EXPECT_FALSE(less_than(small, neg_small)); + + EXPECT_FALSE(less_than(zero, neg_zero)); + EXPECT_FALSE(less_than(neg_zero, zero)); + EXPECT_FALSE(less_than(zero, zero)); + + EXPECT_TRUE(less_than(neg_small, zero)); + EXPECT_TRUE(less_than(neg_zero, small)); + EXPECT_FALSE(less_than(small, zero)); + + EXPECT_TRUE(less_than(neg_inf, inf)); + EXPECT_TRUE(less_than(neg_inf, neg_small)); + EXPECT_TRUE(less_than(small, inf)); + EXPECT_FALSE(less_than(inf, small)); + + EXPECT_FALSE(less_than(small, small)); + EXPECT_FALSE(less_than(neg_inf, neg_inf)); + + auto test_qnan = [&](T x, T y) { + LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); + EXPECT_FALSE(less_than(x, y)); + EXPECT_FP_EXCEPTION(FE_INVALID); + }; + + test_qnan(aNaN, small); + test_qnan(small, aNaN); + test_qnan(aNaN, aNaN); + test_qnan(neg_aNaN, neg_small); + test_qnan(neg_small, neg_aNaN); + test_qnan(neg_aNaN, neg_aNaN); + + auto test_snan = [&](T x, T y) { + LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); + EXPECT_FALSE(less_than(x, y)); + EXPECT_FP_EXCEPTION(FE_INVALID); + }; + + test_snan(sNaN, small); + test_snan(sNaN, neg_small); + test_snan(sNaN, zero); + test_snan(sNaN, inf); + test_snan(sNaN, aNaN); + test_snan(sNaN, sNaN); + + test_snan(neg_sNaN, small); + test_snan(neg_sNaN, neg_small); + test_snan(neg_sNaN, zero); + test_snan(neg_sNaN, inf); + test_snan(neg_sNaN, aNaN); + test_snan(neg_sNaN, neg_sNaN); + } + + void test_greater_than() { + EXPECT_TRUE(greater_than(large, neg_small)); + EXPECT_TRUE(greater_than(neg_small, neg_large)); + + EXPECT_FALSE(greater_than(large, large)); + EXPECT_FALSE(greater_than(neg_small, large)); + + EXPECT_FALSE(greater_than(zero, neg_zero)); + EXPECT_FALSE(greater_than(neg_zero, zero)); + + EXPECT_TRUE(greater_than(inf, neg_inf)); + EXPECT_TRUE(greater_than(inf, large)); + EXPECT_TRUE(greater_than(large, neg_inf)); + EXPECT_FALSE(greater_than(neg_inf, inf)); + + EXPECT_FALSE(greater_than(large, large)); + EXPECT_FALSE(greater_than(inf, inf)); + + auto test_qnan = [&](T x, T y) { + LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); + EXPECT_FALSE(greater_than(x, y)); + EXPECT_FP_EXCEPTION(FE_INVALID); + }; + + test_qnan(aNaN, large); + test_qnan(large, aNaN); + test_qnan(aNaN, aNaN); + test_qnan(neg_aNaN, neg_small); + test_qnan(neg_small, neg_aNaN); + test_qnan(neg_aNaN, neg_aNaN); + + auto test_snan = [&](T x, T y) { + LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); + EXPECT_FALSE(greater_than(x, y)); + EXPECT_FP_EXCEPTION(FE_INVALID); + }; + + test_snan(sNaN, large); + test_snan(sNaN, neg_small); + test_snan(sNaN, zero); + test_snan(sNaN, inf); + test_snan(sNaN, aNaN); + test_snan(sNaN, sNaN); + + test_snan(neg_sNaN, large); + test_snan(neg_sNaN, neg_small); + test_snan(neg_sNaN, zero); + test_snan(neg_sNaN, inf); + test_snan(neg_sNaN, aNaN); + test_snan(neg_sNaN, neg_sNaN); + } + + void test_less_than_or_equals() { + EXPECT_TRUE(less_than_or_equals(neg_small, small)); + EXPECT_TRUE(less_than_or_equals(small, large)); + EXPECT_TRUE(less_than_or_equals(neg_inf, small)); + + EXPECT_TRUE(less_than_or_equals(small, small)); + EXPECT_TRUE(less_than_or_equals(zero, neg_zero)); + EXPECT_TRUE(less_than_or_equals(inf, inf)); + + EXPECT_FALSE(less_than_or_equals(small, neg_small)); + EXPECT_FALSE(less_than_or_equals(large, small)); + EXPECT_FALSE(less_than_or_equals(inf, small)); + + EXPECT_TRUE(less_than_or_equals(neg_large, small)); + EXPECT_FALSE(less_than_or_equals(large, neg_small)); + + auto test_qnan = [&](T x, T y) { + LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); + EXPECT_FALSE(less_than_or_equals(x, y)); + EXPECT_FP_EXCEPTION(FE_INVALID); + }; + + test_qnan(aNaN, small); + test_qnan(small, aNaN); + test_qnan(aNaN, aNaN); + test_qnan(neg_aNaN, neg_small); + test_qnan(neg_small, neg_aNaN); + test_qnan(neg_aNaN, neg_aNaN); + + auto test_snan = [&](T x, T y) { + LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); + EXPECT_FALSE(less_than_or_equals(x, y)); + EXPECT_FP_EXCEPTION(FE_INVALID); + }; + + test_snan(sNaN, small); + test_snan(sNaN, neg_small); + test_snan(sNaN, zero); + test_snan(sNaN, inf); + test_snan(sNaN, aNaN); + test_snan(sNaN, sNaN); + + test_snan(neg_sNaN, small); + test_snan(neg_sNaN, neg_small); + test_snan(neg_sNaN, zero); + test_snan(neg_sNaN, inf); + test_snan(neg_sNaN, aNaN); + test_snan(neg_sNaN, neg_sNaN); + } + + void test_greater_than_or_equals() { + EXPECT_TRUE(greater_than_or_equals(small, neg_small)); + EXPECT_TRUE(greater_than_or_equals(large, small)); + EXPECT_TRUE(greater_than_or_equals(inf, small)); + + EXPECT_TRUE(greater_than_or_equals(small, small)); + EXPECT_TRUE(greater_than_or_equals(zero, neg_zero)); + EXPECT_TRUE(greater_than_or_equals(neg_inf, neg_inf)); + + EXPECT_FALSE(greater_than_or_equals(neg_small, small)); + EXPECT_FALSE(greater_than_or_equals(small, large)); + EXPECT_FALSE(greater_than_or_equals(neg_inf, small)); + + EXPECT_TRUE(greater_than_or_equals(large, neg_small)); + EXPECT_FALSE(greater_than_or_equals(neg_large, small)); + + auto test_qnan = [&](T x, T y) { + LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); + EXPECT_FALSE(greater_than_or_equals(x, y)); + EXPECT_FP_EXCEPTION(FE_INVALID); + }; + + test_qnan(aNaN, small); + test_qnan(small, aNaN); + test_qnan(aNaN, aNaN); + test_qnan(neg_aNaN, neg_small); + test_qnan(neg_small, neg_aNaN); + test_qnan(neg_aNaN, neg_aNaN); + + auto test_snan = [&](T x, T y) { + LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); + EXPECT_FALSE(greater_than_or_equals(x, y)); + EXPECT_FP_EXCEPTION(FE_INVALID); + }; + + test_snan(sNaN, small); + test_snan(sNaN, neg_small); + test_snan(sNaN, zero); + test_snan(sNaN, inf); + test_snan(sNaN, aNaN); + test_snan(sNaN, sNaN); + + test_snan(neg_sNaN, small); + test_snan(neg_sNaN, neg_small); + test_snan(neg_sNaN, zero); + test_snan(neg_sNaN, inf); + test_snan(neg_sNaN, aNaN); + test_snan(neg_sNaN, neg_sNaN); + } +}; + +#define TEST_COMPARISON_OPS(Name, Type) \ + using LlvmLibc##Name##ComparisonOperationsTest = \ + ComparisonOperationsTest; \ + TEST_F(LlvmLibc##Name##ComparisonOperationsTest, Equals) { test_equals(); } \ + TEST_F(LlvmLibc##Name##ComparisonOperationsTest, LessThan) { \ + test_less_than(); \ + } \ + TEST_F(LlvmLibc##Name##ComparisonOperationsTest, GreaterThan) { \ + test_greater_than(); \ + } \ + TEST_F(LlvmLibc##Name##ComparisonOperationsTest, LessThanOrEquals) { \ + test_less_than_or_equals(); \ + } \ + TEST_F(LlvmLibc##Name##ComparisonOperationsTest, GreaterThanOrEquals) { \ + test_greater_than_or_equals(); \ + } + +TEST_COMPARISON_OPS(Float, float) +TEST_COMPARISON_OPS(Double, double) +TEST_COMPARISON_OPS(LongDouble, long double) + +#ifdef LIBC_TYPES_HAS_FLOAT16 +TEST_COMPARISON_OPS(Float16, float16) +#endif // LIBC_TYPES_HAS_FLOAT16 + +#ifdef LIBC_TYPES_HAS_FLOAT128 +TEST_COMPARISON_OPS(Float128, float128) +#endif // LIBC_TYPES_HAS_FLOAT128 + +TEST_COMPARISON_OPS(BFloat16, BFloat16) diff --git a/libc/test/src/__support/File/platform_file_test.cpp b/libc/test/src/__support/File/platform_file_test.cpp index 6b2be2a149329..425da6ce2ad86 100644 --- a/libc/test/src/__support/File/platform_file_test.cpp +++ b/libc/test/src/__support/File/platform_file_test.cpp @@ -21,7 +21,8 @@ LIBC_INLINE File *openfile(const char *file_name, const char *mode) { } TEST(LlvmLibcPlatformFileTest, CreateWriteCloseAndReadBack) { - constexpr char FILENAME[] = "testdata/create_write_close_and_readback.test"; + constexpr char FILENAME[] = + APPEND_LIBC_TEST("testdata/create_write_close_and_readback.test"); File *file = openfile(FILENAME, "w"); ASSERT_FALSE(file == nullptr); ASSERT_EQ(file->write(TEXT, TEXT_SIZE).value, TEXT_SIZE); @@ -42,7 +43,8 @@ TEST(LlvmLibcPlatformFileTest, CreateWriteCloseAndReadBack) { } TEST(LlvmLibcPlatformFileTest, CreateWriteSeekAndReadBack) { - constexpr char FILENAME[] = "testdata/create_write_seek_and_readback.test"; + constexpr char FILENAME[] = + APPEND_LIBC_TEST("testdata/create_write_seek_and_readback.test"); File *file = openfile(FILENAME, "w+"); ASSERT_FALSE(file == nullptr); ASSERT_EQ(file->write(TEXT, TEXT_SIZE).value, TEXT_SIZE); @@ -62,7 +64,8 @@ TEST(LlvmLibcPlatformFileTest, CreateWriteSeekAndReadBack) { } TEST(LlvmLibcPlatformFileTest, CreateAppendCloseAndReadBack) { - constexpr char FILENAME[] = "testdata/create_append_close_and_readback.test"; + constexpr char FILENAME[] = + APPEND_LIBC_TEST("testdata/create_append_close_and_readback.test"); File *file = openfile(FILENAME, "w"); ASSERT_FALSE(file == nullptr); ASSERT_EQ(file->write(TEXT, TEXT_SIZE).value, TEXT_SIZE); @@ -91,7 +94,8 @@ TEST(LlvmLibcPlatformFileTest, CreateAppendCloseAndReadBack) { } TEST(LlvmLibcPlatformFileTest, CreateAppendSeekAndReadBack) { - constexpr char FILENAME[] = "testdata/create_append_seek_and_readback.test"; + constexpr char FILENAME[] = + APPEND_LIBC_TEST("testdata/create_append_seek_and_readback.test"); File *file = openfile(FILENAME, "w"); ASSERT_FALSE(file == nullptr); ASSERT_EQ(file->write(TEXT, TEXT_SIZE).value, TEXT_SIZE); @@ -124,7 +128,7 @@ TEST(LlvmLibcPlatformFileTest, LargeFile) { for (size_t i = 0; i < DATA_SIZE; ++i) write_data[i] = BYTE; - constexpr char FILENAME[] = "testdata/large_file.test"; + constexpr char FILENAME[] = APPEND_LIBC_TEST("testdata/large_file.test"); File *file = openfile(FILENAME, "w"); ASSERT_FALSE(file == nullptr); @@ -151,7 +155,8 @@ TEST(LlvmLibcPlatformFileTest, LargeFile) { } TEST(LlvmLibcPlatformFileTest, ReadSeekCurAndRead) { - constexpr char FILENAME[] = "testdata/read_seek_cur_and_read.test"; + constexpr char FILENAME[] = + APPEND_LIBC_TEST("testdata/read_seek_cur_and_read.test"); File *file = openfile(FILENAME, "w"); ASSERT_FALSE(file == nullptr); constexpr char CONTENT[] = "1234567890987654321"; @@ -178,7 +183,8 @@ TEST(LlvmLibcPlatformFileTest, ReadSeekCurAndRead) { } TEST(LlvmLibcPlatformFileTest, IncorrectOperation) { - constexpr char FILENAME[] = "testdata/incorrect_operation.test"; + constexpr char FILENAME[] = + APPEND_LIBC_TEST("testdata/incorrect_operation.test"); char data[1] = {123}; File *file = openfile(FILENAME, "w"); diff --git a/libc/test/src/__support/wchar/string_converter_test.cpp b/libc/test/src/__support/wchar/string_converter_test.cpp index 14d074156d033..d514df9317852 100644 --- a/libc/test/src/__support/wchar/string_converter_test.cpp +++ b/libc/test/src/__support/wchar/string_converter_test.cpp @@ -245,6 +245,63 @@ TEST(LlvmLibcStringConverterTest, UTF8To32ErrorHandling) { ASSERT_EQ(static_cast(sc.getSourceIndex()), 4); } +TEST(LlvmLibcStringConverterTest, InvalidCharacterOutsideBounds) { + // if an invalid character exists in the source string but we don't have space + // to write it, we should return a "stop converting" error rather than an + // invalid character error + + // first 4 bytes are clown emoji (🤡) + // next 3 form an invalid character + const char *src1 = "\xF0\x9F\xA4\xA1\x90\x88\x30"; + LIBC_NAMESPACE::internal::mbstate ps1; + LIBC_NAMESPACE::internal::StringConverter sc1( + reinterpret_cast(src1), &ps1, 1); + + auto res1 = sc1.popUTF32(); + ASSERT_TRUE(res1.has_value()); + ASSERT_EQ(static_cast(res1.value()), 0x1f921); + ASSERT_EQ(static_cast(sc1.getSourceIndex()), 4); + + res1 = sc1.popUTF32(); + ASSERT_FALSE(res1.has_value()); + // no space to write error NOT invalid character error (EILSEQ) + ASSERT_EQ(static_cast(res1.error()), -1); + ASSERT_EQ(static_cast(sc1.getSourceIndex()), 4); + + const wchar_t src2[] = { + static_cast(0x1f921), static_cast(0xffffff), + static_cast(0x0)}; // clown emoji, invalid utf32 + LIBC_NAMESPACE::internal::mbstate ps2; + LIBC_NAMESPACE::internal::StringConverter sc2( + reinterpret_cast(src2), &ps2, 4); + + auto res2 = sc2.popUTF8(); + ASSERT_TRUE(res2.has_value()); + ASSERT_EQ(static_cast(res2.value()), 0xF0); + ASSERT_EQ(static_cast(sc2.getSourceIndex()), 1); + + res2 = sc2.popUTF8(); + ASSERT_TRUE(res2.has_value()); + ASSERT_EQ(static_cast(res2.value()), 0x9F); + ASSERT_EQ(static_cast(sc2.getSourceIndex()), 1); + + res2 = sc2.popUTF8(); + ASSERT_TRUE(res2.has_value()); + ASSERT_EQ(static_cast(res2.value()), 0xA4); + ASSERT_EQ(static_cast(sc2.getSourceIndex()), 1); + + res2 = sc2.popUTF8(); + ASSERT_TRUE(res2.has_value()); + ASSERT_EQ(static_cast(res2.value()), 0xA1); + ASSERT_EQ(static_cast(sc2.getSourceIndex()), 1); + + res2 = sc2.popUTF8(); + ASSERT_FALSE(res2.has_value()); + // no space to write error NOT invalid character error (EILSEQ) + ASSERT_EQ(static_cast(res2.error()), -1); + ASSERT_EQ(static_cast(sc2.getSourceIndex()), 1); +} + TEST(LlvmLibcStringConverterTest, MultipleStringConverters32To8) { /* We do NOT test partially popping a character and expecting the next diff --git a/libc/test/src/math/cospif_test.cpp b/libc/test/src/math/cospif_test.cpp index cb88bfcade0dc..5c30fb7c8718f 100644 --- a/libc/test/src/math/cospif_test.cpp +++ b/libc/test/src/math/cospif_test.cpp @@ -100,7 +100,7 @@ TEST_F(LlvmLibcCospifTest, SmallValues) { LIBC_NAMESPACE::cospif(x), 0.5); } -// SDCOMP-26094: check sinfpi in the cases for which the range reducer +// SDCOMP-26094: check cospif in the cases for which the range reducer // returns values furthest beyond its nominal upper bound of pi/4. TEST_F(LlvmLibcCospifTest, SDCOMP_26094) { for (uint32_t v : SDCOMP26094_VALUES) { diff --git a/libc/test/src/math/explogxf_test.cpp b/libc/test/src/math/explogxf_test.cpp index 01197b835433f..49cc96291a392 100644 --- a/libc/test/src/math/explogxf_test.cpp +++ b/libc/test/src/math/explogxf_test.cpp @@ -43,12 +43,8 @@ TEST_F(LlvmLibcExplogfTest, ExpInFloatRange) { def_prec); } -TEST_F(LlvmLibcExplogfTest, Log2InFloatRange) { - CHECK_DATA(0.0f, inf, mpfr::Operation::Log2, LIBC_NAMESPACE::log2_eval, - f_normal, def_count, def_prec); -} - TEST_F(LlvmLibcExplogfTest, LogInFloatRange) { - CHECK_DATA(0.0f, inf, mpfr::Operation::Log, LIBC_NAMESPACE::log_eval, - f_normal, def_count, def_prec); + CHECK_DATA(0.0f, inf, mpfr::Operation::Log, + LIBC_NAMESPACE::acoshf_internal::log_eval, f_normal, def_count, + def_prec); } diff --git a/libc/test/src/math/sincosf_test.cpp b/libc/test/src/math/sincosf_test.cpp index ad2155f329cd9..4aac1fabfbd62 100644 --- a/libc/test/src/math/sincosf_test.cpp +++ b/libc/test/src/math/sincosf_test.cpp @@ -164,7 +164,7 @@ TEST_F(LlvmLibcSinCosfTest, SpecialValues) { } } -// SDCOMP-26094: check sinf in the cases for which the range reducer +// SDCOMP-26094: check sincosf in the cases for which the range reducer // returns values furthest beyond its nominal upper bound of pi/4. TEST_F(LlvmLibcSinCosfTest, SDCOMP_26094) { for (uint32_t v : SDCOMP26094_VALUES) { diff --git a/libc/test/src/math/sinpif_test.cpp b/libc/test/src/math/sinpif_test.cpp index 986c676761f0e..94e3dbc4f07d4 100644 --- a/libc/test/src/math/sinpif_test.cpp +++ b/libc/test/src/math/sinpif_test.cpp @@ -100,7 +100,7 @@ TEST_F(LlvmLibcSinpifTest, SmallValues) { LIBC_NAMESPACE::sinpif(x), 0.5); } -// SDCOMP-26094: check sinfpi in the cases for which the range reducer +// SDCOMP-26094: check sinpif in the cases for which the range reducer // returns values furthest beyond its nominal upper bound of pi/4. TEST_F(LlvmLibcSinpifTest, SDCOMP_26094) { for (uint32_t v : SDCOMP26094_VALUES) { diff --git a/libc/test/src/stdio/fdopen_test.cpp b/libc/test/src/stdio/fdopen_test.cpp index b53184c30be36..bab1d33edcb04 100644 --- a/libc/test/src/stdio/fdopen_test.cpp +++ b/libc/test/src/stdio/fdopen_test.cpp @@ -24,7 +24,8 @@ using LlvmLibcStdioFdopenTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest; TEST_F(LlvmLibcStdioFdopenTest, WriteAppendRead) { using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; - constexpr const char *TEST_FILE_NAME = "testdata/write_read_append.test"; + constexpr const char *TEST_FILE_NAME = + APPEND_LIBC_TEST("testdata/write_read_append.test"); auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME); int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); auto *fp = LIBC_NAMESPACE::fdopen(fd, "w"); @@ -54,7 +55,8 @@ TEST_F(LlvmLibcStdioFdopenTest, WriteAppendRead) { } TEST_F(LlvmLibcStdioFdopenTest, InvalidFd) { - constexpr const char *TEST_FILE_NAME = "testdata/invalid_fd.test"; + constexpr const char *TEST_FILE_NAME = + APPEND_LIBC_TEST("testdata/invalid_fd.test"); auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME); int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC); LIBC_NAMESPACE::close(fd); @@ -65,7 +67,8 @@ TEST_F(LlvmLibcStdioFdopenTest, InvalidFd) { } TEST_F(LlvmLibcStdioFdopenTest, InvalidMode) { - constexpr const char *TEST_FILE_NAME = "testdata/invalid_mode.test"; + constexpr const char *TEST_FILE_NAME = + APPEND_LIBC_TEST("testdata/invalid_mode.test"); auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME); int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_RDONLY, S_IRWXU); ASSERT_ERRNO_SUCCESS(); diff --git a/libc/test/src/stdio/fgetc_test.cpp b/libc/test/src/stdio/fgetc_test.cpp index be2e50271b510..1d242a0475aba 100644 --- a/libc/test/src/stdio/fgetc_test.cpp +++ b/libc/test/src/stdio/fgetc_test.cpp @@ -56,9 +56,10 @@ class LlvmLibcGetcTest : public LIBC_NAMESPACE::testing::ErrnoCheckingTest { }; TEST_F(LlvmLibcGetcTest, WriteAndReadCharactersWithFgetc) { - test_with_func(&LIBC_NAMESPACE::fgetc, "testdata/fgetc.test"); + test_with_func(&LIBC_NAMESPACE::fgetc, + APPEND_LIBC_TEST("testdata/fgetc.test")); } TEST_F(LlvmLibcGetcTest, WriteAndReadCharactersWithGetc) { - test_with_func(&LIBC_NAMESPACE::getc, "testdata/getc.test"); + test_with_func(&LIBC_NAMESPACE::getc, APPEND_LIBC_TEST("testdata/getc.test")); } diff --git a/libc/test/src/stdio/fgetc_unlocked_test.cpp b/libc/test/src/stdio/fgetc_unlocked_test.cpp index bef9dafd3d87c..16d79211f5e8f 100644 --- a/libc/test/src/stdio/fgetc_unlocked_test.cpp +++ b/libc/test/src/stdio/fgetc_unlocked_test.cpp @@ -62,9 +62,10 @@ class LlvmLibcGetcTest : public LIBC_NAMESPACE::testing::ErrnoCheckingTest { TEST_F(LlvmLibcGetcTest, WriteAndReadCharactersWithFgetcUnlocked) { test_with_func(&LIBC_NAMESPACE::fgetc_unlocked, - "testdata/fgetc_unlocked.test"); + APPEND_LIBC_TEST("testdata/fgetc_unlocked.test")); } TEST_F(LlvmLibcGetcTest, WriteAndReadCharactersWithGetcUnlocked) { - test_with_func(&LIBC_NAMESPACE::getc_unlocked, "testdata/getc_unlocked.test"); + test_with_func(&LIBC_NAMESPACE::getc_unlocked, + APPEND_LIBC_TEST("testdata/getc_unlocked.test")); } diff --git a/libc/test/src/stdio/fgets_test.cpp b/libc/test/src/stdio/fgets_test.cpp index 8fc38b0659181..14f054eee1339 100644 --- a/libc/test/src/stdio/fgets_test.cpp +++ b/libc/test/src/stdio/fgets_test.cpp @@ -20,7 +20,7 @@ using LlvmLibcFgetsTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest; using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher; TEST_F(LlvmLibcFgetsTest, WriteAndReadCharacters) { - constexpr char FILENAME[] = "testdata/fgets.test"; + constexpr char FILENAME[] = APPEND_LIBC_TEST("testdata/fgets.test"); ::FILE *file = LIBC_NAMESPACE::fopen(FILENAME, "w"); ASSERT_FALSE(file == nullptr); constexpr char CONTENT[] = "123456789\n" diff --git a/libc/test/src/stdio/fileop_test.cpp b/libc/test/src/stdio/fileop_test.cpp index e097785832d56..02328042b92b3 100644 --- a/libc/test/src/stdio/fileop_test.cpp +++ b/libc/test/src/stdio/fileop_test.cpp @@ -29,7 +29,8 @@ using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::NE; using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::returns; TEST_F(LlvmLibcFILETest, SimpleFileOperations) { - constexpr char FILENAME[] = "testdata/simple_operations.test"; + constexpr char FILENAME[] = + APPEND_LIBC_TEST("testdata/simple_operations.test"); ::FILE *file = LIBC_NAMESPACE::fopen(FILENAME, "w"); ASSERT_FALSE(file == nullptr); ASSERT_GE(LIBC_NAMESPACE::fileno(file), 0); @@ -127,7 +128,7 @@ TEST_F(LlvmLibcFILETest, SimpleFileOperations) { } TEST_F(LlvmLibcFILETest, FFlush) { - constexpr char FILENAME[] = "testdata/fflush.test"; + constexpr char FILENAME[] = APPEND_LIBC_TEST("testdata/fflush.test"); ::FILE *file = LIBC_NAMESPACE::fopen(FILENAME, "w+"); ASSERT_FALSE(file == nullptr); constexpr char CONTENT[] = "1234567890987654321"; @@ -154,7 +155,7 @@ TEST_F(LlvmLibcFILETest, FOpenFWriteSizeGreaterThanOne) { }; constexpr MyStruct WRITE_DATA[] = {{'a', 1}, {'b', 2}, {'c', 3}}; constexpr size_t WRITE_NMEMB = sizeof(WRITE_DATA) / sizeof(MyStruct); - constexpr char FILENAME[] = "testdata/fread_fwrite.test"; + constexpr char FILENAME[] = APPEND_LIBC_TEST("testdata/fread_fwrite.test"); FILE *file = LIBC_NAMESPACE::fopen(FILENAME, "w"); ASSERT_FALSE(file == nullptr); diff --git a/libc/test/src/stdio/fopen_test.cpp b/libc/test/src/stdio/fopen_test.cpp index 42e7c57cffe04..3f651f755e7f3 100644 --- a/libc/test/src/stdio/fopen_test.cpp +++ b/libc/test/src/stdio/fopen_test.cpp @@ -17,7 +17,8 @@ TEST(LlvmLibcFOpenTest, PrintToFile) { int result; - FILE *file = LIBC_NAMESPACE::fopen("./testdata/test_data.txt", "w"); + FILE *file = + LIBC_NAMESPACE::fopen(APPEND_LIBC_TEST("testdata/test.txt"), "w"); ASSERT_FALSE(file == nullptr); static constexpr char STRING[] = "A simple string written to a file\n"; @@ -26,7 +27,8 @@ TEST(LlvmLibcFOpenTest, PrintToFile) { ASSERT_EQ(0, LIBC_NAMESPACE::fclose(file)); - FILE *new_file = LIBC_NAMESPACE::fopen("./testdata/test_data.txt", "r"); + FILE *new_file = + LIBC_NAMESPACE::fopen(APPEND_LIBC_TEST("testdata/test.txt"), "r"); ASSERT_FALSE(new_file == nullptr); static char data[64] = {0}; diff --git a/libc/test/src/stdio/fprintf_test.cpp b/libc/test/src/stdio/fprintf_test.cpp index 82a3e039d9baa..6799323cc6ad9 100644 --- a/libc/test/src/stdio/fprintf_test.cpp +++ b/libc/test/src/stdio/fprintf_test.cpp @@ -32,7 +32,7 @@ using ::fread; } // namespace printf_test TEST(LlvmLibcFPrintfTest, WriteToFile) { - const char *FILENAME = "fprintf_output.test"; + const char *FILENAME = APPEND_LIBC_TEST("fprintf_output.test"); auto FILE_PATH = libc_make_test_file_path(FILENAME); ::FILE *file = printf_test::fopen(FILE_PATH, "w"); diff --git a/libc/test/src/stdio/fscanf_test.cpp b/libc/test/src/stdio/fscanf_test.cpp index e5b8c4f422bac..451ff94055ea5 100644 --- a/libc/test/src/stdio/fscanf_test.cpp +++ b/libc/test/src/stdio/fscanf_test.cpp @@ -34,7 +34,7 @@ using ::fwrite; } // namespace scanf_test TEST(LlvmLibcFScanfTest, WriteToFile) { - const char *FILENAME = "fscanf_output.test"; + const char *FILENAME = APPEND_LIBC_TEST("fscanf_output.test"); auto FILE_PATH = libc_make_test_file_path(FILENAME); ::FILE *file = scanf_test::fopen(FILE_PATH, "w"); ASSERT_FALSE(file == nullptr); diff --git a/libc/test/src/stdio/ftell_test.cpp b/libc/test/src/stdio/ftell_test.cpp index 01ff071f2ee78..1f762f38585bc 100644 --- a/libc/test/src/stdio/ftell_test.cpp +++ b/libc/test/src/stdio/ftell_test.cpp @@ -21,7 +21,7 @@ class LlvmLibcFTellTest : public LIBC_NAMESPACE::testing::Test { protected: void test_with_bufmode(int bufmode) { - constexpr char FILENAME[] = "testdata/ftell.test"; + constexpr char FILENAME[] = APPEND_LIBC_TEST("testdata/ftell.test"); // We will set a special buffer to the file so that we guarantee buffering. constexpr size_t BUFFER_SIZE = 1024; char buffer[BUFFER_SIZE]; diff --git a/libc/test/src/stdio/putc_test.cpp b/libc/test/src/stdio/putc_test.cpp index e881a0e2d0108..6bf482794f0b8 100644 --- a/libc/test/src/stdio/putc_test.cpp +++ b/libc/test/src/stdio/putc_test.cpp @@ -16,7 +16,7 @@ #include "test/UnitTest/Test.h" TEST(LlvmLibcPutcTest, WriteToFile) { - constexpr char FILENAME[] = "testdata/putc_output.test"; + constexpr char FILENAME[] = APPEND_LIBC_TEST("testdata/putc_output.test"); ::FILE *file = LIBC_NAMESPACE::fopen(FILENAME, "w"); ASSERT_FALSE(file == nullptr); diff --git a/libc/test/src/stdio/remove_test.cpp b/libc/test/src/stdio/remove_test.cpp index 296bff1f5dc15..20d166f0acb2f 100644 --- a/libc/test/src/stdio/remove_test.cpp +++ b/libc/test/src/stdio/remove_test.cpp @@ -25,7 +25,7 @@ TEST_F(LlvmLibcRemoveTest, CreateAndRemoveFile) { using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails; using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; - constexpr const char *FILENAME = "remove.test.file"; + constexpr const char *FILENAME = APPEND_LIBC_TEST("remove.test.file"); auto TEST_FILE = libc_make_test_file_path(FILENAME); int fd = LIBC_NAMESPACE::open(TEST_FILE, O_WRONLY | O_CREAT, S_IRWXU); ASSERT_ERRNO_SUCCESS(); @@ -42,7 +42,7 @@ TEST_F(LlvmLibcRemoveTest, CreateAndRemoveDir) { // it was removed. using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails; using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; - constexpr const char *FILENAME = "remove.test.dir"; + constexpr const char *FILENAME = APPEND_LIBC_TEST("remove.test.dir"); auto TEST_DIR = libc_make_test_file_path(FILENAME); ASSERT_THAT(LIBC_NAMESPACE::mkdirat(AT_FDCWD, TEST_DIR, S_IRWXU), Succeeds(0)); diff --git a/libc/test/src/stdio/rename_test.cpp b/libc/test/src/stdio/rename_test.cpp index 135fb98c07fbb..af957e0fcbf79 100644 --- a/libc/test/src/stdio/rename_test.cpp +++ b/libc/test/src/stdio/rename_test.cpp @@ -24,7 +24,7 @@ TEST_F(LlvmLibcRenameTest, CreateAndRenameFile) { using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails; using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; - constexpr const char *FILENAME0 = "rename.test.file0"; + constexpr const char *FILENAME0 = APPEND_LIBC_TEST("rename.test.file0"); auto TEST_FILEPATH0 = libc_make_test_file_path(FILENAME0); int fd = LIBC_NAMESPACE::open(TEST_FILEPATH0, O_WRONLY | O_CREAT, S_IRWXU); @@ -33,7 +33,7 @@ TEST_F(LlvmLibcRenameTest, CreateAndRenameFile) { ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0)); ASSERT_THAT(LIBC_NAMESPACE::access(TEST_FILEPATH0, F_OK), Succeeds(0)); - constexpr const char *FILENAME1 = "rename.test.file1"; + constexpr const char *FILENAME1 = APPEND_LIBC_TEST("rename.test.file1"); auto TEST_FILEPATH1 = libc_make_test_file_path(FILENAME1); ASSERT_THAT(LIBC_NAMESPACE::rename(TEST_FILEPATH0, TEST_FILEPATH1), Succeeds(0)); @@ -44,7 +44,7 @@ TEST_F(LlvmLibcRenameTest, CreateAndRenameFile) { TEST_F(LlvmLibcRenameTest, RenameNonExistent) { using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails; - constexpr const char *FILENAME1 = "rename.test.file1"; + constexpr const char *FILENAME1 = APPEND_LIBC_TEST("rename.test.file1"); auto TEST_FILEPATH1 = libc_make_test_file_path(FILENAME1); ASSERT_THAT(LIBC_NAMESPACE::rename("non-existent", TEST_FILEPATH1), diff --git a/libc/test/src/stdio/setbuf_test.cpp b/libc/test/src/stdio/setbuf_test.cpp index 25fea59076626..f1f98f7040402 100644 --- a/libc/test/src/stdio/setbuf_test.cpp +++ b/libc/test/src/stdio/setbuf_test.cpp @@ -18,7 +18,8 @@ TEST(LlvmLibcSetbufTest, DefaultBufsize) { // The idea in this test is to change the buffer after opening a file and // ensure that read and write work as expected. - constexpr char FILENAME[] = "testdata/setbuf_test_default_bufsize.test"; + constexpr char FILENAME[] = + APPEND_LIBC_TEST("testdata/setbuf_test_default_bufsize.test"); ::FILE *file = LIBC_NAMESPACE::fopen(FILENAME, "w"); ASSERT_FALSE(file == nullptr); char buffer[BUFSIZ]; @@ -41,7 +42,8 @@ TEST(LlvmLibcSetbufTest, DefaultBufsize) { TEST(LlvmLibcSetbufTest, NullBuffer) { // The idea in this test is that we set a null buffer and ensure that // everything works correctly. - constexpr char FILENAME[] = "testdata/setbuf_test_null_buffer.test"; + constexpr char FILENAME[] = + APPEND_LIBC_TEST("testdata/setbuf_test_null_buffer.test"); ::FILE *file = LIBC_NAMESPACE::fopen(FILENAME, "w"); ASSERT_FALSE(file == nullptr); LIBC_NAMESPACE::setbuf(file, nullptr); diff --git a/libc/test/src/stdio/setvbuf_test.cpp b/libc/test/src/stdio/setvbuf_test.cpp index a0936ba79ef73..f55b8e2c3c722 100644 --- a/libc/test/src/stdio/setvbuf_test.cpp +++ b/libc/test/src/stdio/setvbuf_test.cpp @@ -23,7 +23,7 @@ TEST_F(LlvmLibcSetvbufTest, SetNBFBuffer) { // then set a NBF buffer to the write handle. Since it is NBF, the data // written using the write handle should be immediately readable by the read // handle. - constexpr char FILENAME[] = "testdata/setvbuf_nbf.test"; + constexpr char FILENAME[] = APPEND_LIBC_TEST("testdata/setvbuf_nbf.test"); ::FILE *fw = LIBC_NAMESPACE::fopen(FILENAME, "w"); ASSERT_FALSE(fw == nullptr); @@ -59,7 +59,7 @@ TEST_F(LlvmLibcSetvbufTest, SetLBFBuffer) { // then set a LBF buffer to the write handle. Since it is LBF, the data // written using the write handle should be available right after a '\n' is // written. - constexpr char FILENAME[] = "testdata/setvbuf_lbf.test"; + constexpr char FILENAME[] = APPEND_LIBC_TEST("testdata/setvbuf_lbf.test"); ::FILE *fw = LIBC_NAMESPACE::fopen(FILENAME, "w"); ASSERT_FALSE(fw == nullptr); @@ -96,7 +96,8 @@ TEST_F(LlvmLibcSetvbufTest, SetLBFBuffer) { } TEST(LlvmLibcSetbufTest, InvalidBufferMode) { - constexpr char FILENAME[] = "testdata/setvbuf_invalid_bufmode.test"; + constexpr char FILENAME[] = + APPEND_LIBC_TEST("testdata/setvbuf_invalid_bufmode.test"); ::FILE *f = LIBC_NAMESPACE::fopen(FILENAME, "w"); ASSERT_FALSE(f == nullptr); char buf[BUFSIZ]; diff --git a/libc/test/src/stdio/ungetc_test.cpp b/libc/test/src/stdio/ungetc_test.cpp index b9d7530fc7177..917dbc2a77ab4 100644 --- a/libc/test/src/stdio/ungetc_test.cpp +++ b/libc/test/src/stdio/ungetc_test.cpp @@ -17,7 +17,7 @@ #include "test/UnitTest/Test.h" TEST(LlvmLibcUngetcTest, UngetAndReadBack) { - constexpr char FILENAME[] = "testdata/ungetc_test.test"; + constexpr char FILENAME[] = APPEND_LIBC_TEST("testdata/ungetc_test.test"); ::FILE *file = LIBC_NAMESPACE::fopen(FILENAME, "w"); ASSERT_FALSE(file == nullptr); constexpr char CONTENT[] = "abcdef"; diff --git a/libc/test/src/stdio/unlocked_fileop_test.cpp b/libc/test/src/stdio/unlocked_fileop_test.cpp index e99b382d12112..7af7eca46a1ec 100644 --- a/libc/test/src/stdio/unlocked_fileop_test.cpp +++ b/libc/test/src/stdio/unlocked_fileop_test.cpp @@ -21,7 +21,8 @@ using LlvmLibcFILETest = LIBC_NAMESPACE::testing::ErrnoCheckingTest; TEST_F(LlvmLibcFILETest, UnlockedReadAndWrite) { - constexpr char fNAME[] = "testdata/unlocked_read_and_write.test"; + constexpr char fNAME[] = + APPEND_LIBC_TEST("testdata/unlocked_read_and_write.test"); ::FILE *f = LIBC_NAMESPACE::fopen(fNAME, "w"); ASSERT_FALSE(f == nullptr); constexpr char CONTENT[] = "1234567890987654321"; diff --git a/libc/test/src/stdio/vfprintf_test.cpp b/libc/test/src/stdio/vfprintf_test.cpp index 80d484500d5f2..f50565a0f68ca 100644 --- a/libc/test/src/stdio/vfprintf_test.cpp +++ b/libc/test/src/stdio/vfprintf_test.cpp @@ -45,7 +45,7 @@ int call_vfprintf(::FILE *__restrict stream, const char *__restrict format, } TEST(LlvmLibcVFPrintfTest, WriteToFile) { - const char *FILENAME = "vfprintf_output.test"; + const char *FILENAME = APPEND_LIBC_TEST("vfprintf_output.test"); auto FILE_PATH = libc_make_test_file_path(FILENAME); ::FILE *file = printf_test::fopen(FILE_PATH, "w"); diff --git a/libc/test/src/stdio/vfscanf_test.cpp b/libc/test/src/stdio/vfscanf_test.cpp index b66538671f620..38a64611d0705 100644 --- a/libc/test/src/stdio/vfscanf_test.cpp +++ b/libc/test/src/stdio/vfscanf_test.cpp @@ -42,7 +42,7 @@ static int call_vfscanf(::FILE *stream, const char *__restrict format, ...) { } TEST(LlvmLibcVFScanfTest, WriteToFile) { - const char *FILENAME = "vfscanf_output.test"; + const char *FILENAME = APPEND_LIBC_TEST("vfscanf_output.test"); auto FILE_PATH = libc_make_test_file_path(FILENAME); ::FILE *file = scanf_test::fopen(FILE_PATH, "w"); ASSERT_FALSE(file == nullptr); diff --git a/libc/test/src/sys/epoll/linux/epoll_create_test.cpp b/libc/test/src/sys/epoll/linux/epoll_create_test.cpp index 06c17c6cf29e6..2bbfe4fbe81ff 100644 --- a/libc/test/src/sys/epoll/linux/epoll_create_test.cpp +++ b/libc/test/src/sys/epoll/linux/epoll_create_test.cpp @@ -10,7 +10,6 @@ #include "test/UnitTest/ErrnoCheckingTest.h" #include "test/UnitTest/ErrnoSetterMatcher.h" #include "test/UnitTest/Test.h" -#include // For syscall numbers. using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher; using LlvmLibcEpollCreateTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest; @@ -23,8 +22,6 @@ TEST_F(LlvmLibcEpollCreateTest, Basic) { ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds()); } -#ifdef SYS_epoll_create TEST_F(LlvmLibcEpollCreateTest, Fails) { ASSERT_THAT(LIBC_NAMESPACE::epoll_create(0), Fails(EINVAL)); } -#endif diff --git a/libc/test/src/wchar/mbrtowc_test.cpp b/libc/test/src/wchar/mbrtowc_test.cpp index 5a14d8e25935c..c406300b9ca34 100644 --- a/libc/test/src/wchar/mbrtowc_test.cpp +++ b/libc/test/src/wchar/mbrtowc_test.cpp @@ -190,6 +190,18 @@ TEST_F(LlvmLibcMBRToWCTest, NullString) { ASSERT_ERRNO_SUCCESS(); } +TEST_F(LlvmLibcMBRToWCTest, NullDest) { + const char ch[4] = {static_cast(0xF0), static_cast(0x9F), + static_cast(0xA4), + static_cast(0xA1)}; // 🤡 clown emoji + mbstate_t *mb; + LIBC_NAMESPACE::memset(&mb, 0, sizeof(mbstate_t)); + // reading nullptr should return correct size + size_t n = LIBC_NAMESPACE::mbrtowc(nullptr, ch, 10, mb); + ASSERT_EQ(static_cast(n), 4); + ASSERT_ERRNO_SUCCESS(); +} + TEST_F(LlvmLibcMBRToWCTest, InvalidMBState) { const char ch[4] = {static_cast(0xC2), static_cast(0x8E), static_cast(0xC7), static_cast(0x8C)}; diff --git a/libc/test/src/wctype/CMakeLists.txt b/libc/test/src/wctype/CMakeLists.txt new file mode 100644 index 0000000000000..5459cdb4a9b71 --- /dev/null +++ b/libc/test/src/wctype/CMakeLists.txt @@ -0,0 +1,11 @@ +add_custom_target(libc_wctype_unittests) + +add_libc_test( + iswalpha_test + SUITE + libc_wctype_unittests + SRCS + iswalpha_test.cpp + DEPENDS + libc.src.wctype.iswalpha +) diff --git a/libc/test/src/wctype/iswalpha_test.cpp b/libc/test/src/wctype/iswalpha_test.cpp new file mode 100644 index 0000000000000..f3f75f4dc7aa5 --- /dev/null +++ b/libc/test/src/wctype/iswalpha_test.cpp @@ -0,0 +1,54 @@ +//===-- Unittests for iswalpha --------------------------------------------===// +// +// 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 "src/__support/CPP/span.h" +#include "src/wctype/iswalpha.h" + +#include "test/UnitTest/LibcTest.h" +#include "test/UnitTest/Test.h" + +namespace { + +// TODO: Merge the wctype tests using this framework. +constexpr char WALPHA_ARRAY[] = { + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', +}; + +bool in_span(int ch, LIBC_NAMESPACE::cpp::span arr) { + for (size_t i = 0; i < arr.size(); ++i) + if (static_cast(arr[i]) == ch) + return true; + return false; +} + +} // namespace + +TEST(LlvmLibciswalpha, SimpleTest) { + EXPECT_TRUE(LIBC_NAMESPACE::iswalpha('a')); + EXPECT_TRUE(LIBC_NAMESPACE::iswalpha('B')); + + EXPECT_FALSE(LIBC_NAMESPACE::iswalpha('3')); + EXPECT_FALSE(LIBC_NAMESPACE::iswalpha(' ')); + EXPECT_FALSE(LIBC_NAMESPACE::iswalpha('?')); + EXPECT_FALSE(LIBC_NAMESPACE::iswalpha('\0')); + EXPECT_FALSE(LIBC_NAMESPACE::iswalpha(-1)); +} + +TEST(LlvmLibciswalpha, DefaultLocale) { + // Loops through all characters, verifying that letters return + // true and everything else returns false. + for (int ch = -255; ch < 255; ++ch) { + if (in_span(ch, WALPHA_ARRAY)) + EXPECT_TRUE(LIBC_NAMESPACE::iswalpha(ch)); + else + EXPECT_FALSE(LIBC_NAMESPACE::iswalpha(ch)); + } +} diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt index 2570d1a106d21..e4e9a74639b17 100644 --- a/libclc/CMakeLists.txt +++ b/libclc/CMakeLists.txt @@ -405,6 +405,7 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} ) -I${CMAKE_CURRENT_SOURCE_DIR}/clc/include # Error on undefined macros -Werror=undef + -fdiscard-value-names ) if( NOT "${cpu}" STREQUAL "" ) diff --git a/libclc/clc/include/clc/atomic/atomic_decl.inc b/libclc/clc/include/clc/atomic/atomic_decl.inc new file mode 100644 index 0000000000000..b790a94c7d288 --- /dev/null +++ b/libclc/clc/include/clc/atomic/atomic_decl.inc @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// MemoryOrder is memory order supported by Clang __scoped_atomic* builtins. +// MemoryScope is memory scope supported by Clang __scoped_atomic* builtins. + +#ifdef __CLC_SCALAR +#if defined(__CLC_FPSIZE) || (__CLC_GENSIZE >= 32) + +#ifdef __CLC_NO_VALUE_ARG +#define __CLC_DECLARE_ATOMIC(ADDRSPACE) \ + _CLC_OVERLOAD _CLC_DECL __CLC_GENTYPE FUNCTION( \ + volatile ADDRSPACE __CLC_GENTYPE *Ptr, int MemoryOrder, \ + int MemoryScope); +#elif defined(__CLC_RETURN_VOID) +#define __CLC_DECLARE_ATOMIC(ADDRSPACE) \ + _CLC_OVERLOAD _CLC_DECL void FUNCTION(volatile ADDRSPACE __CLC_GENTYPE *Ptr, \ + __CLC_GENTYPE Value, int MemoryOrder, \ + int MemoryScope); +#elif defined(__CLC_COMPARE_EXCHANGE) +#define __CLC_DECLARE_ATOMIC(ADDRSPACE) \ + _CLC_OVERLOAD _CLC_DECL __CLC_GENTYPE FUNCTION( \ + volatile ADDRSPACE __CLC_GENTYPE *Ptr, __CLC_GENTYPE Comparator, \ + __CLC_GENTYPE Value, int MemoryOrderEqual, int MemoryOrderUnequal, \ + int MemoryScope); +#else +#define __CLC_DECLARE_ATOMIC(ADDRSPACE) \ + _CLC_OVERLOAD _CLC_DECL __CLC_GENTYPE FUNCTION( \ + volatile ADDRSPACE __CLC_GENTYPE *Ptr, __CLC_GENTYPE Value, \ + int MemoryOrder, int MemoryScope); +#endif + +__CLC_DECLARE_ATOMIC(global) +__CLC_DECLARE_ATOMIC(local) +#if _CLC_GENERIC_AS_SUPPORTED +__CLC_DECLARE_ATOMIC() +#endif + +#undef __CLC_DECLARE_ATOMIC + +#endif // defined(__CLC_FPSIZE) || (__CLC_GENSIZE >= 32) +#endif // __CLC_SCALAR diff --git a/libclc/clc/include/clc/atomic/clc_atomic_compare_exchange.h b/libclc/clc/include/clc/atomic/clc_atomic_compare_exchange.h new file mode 100644 index 0000000000000..ae7918ac32e43 --- /dev/null +++ b/libclc/clc/include/clc/atomic/clc_atomic_compare_exchange.h @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef __CLC_ATOMIC_CLC_ATOMIC_COMPARE_EXCHANGE_H__ +#define __CLC_ATOMIC_CLC_ATOMIC_COMPARE_EXCHANGE_H__ + +#include + +#define FUNCTION __clc_atomic_compare_exchange +#define __CLC_COMPARE_EXCHANGE + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#undef __CLC_COMPARE_EXCHANGE +#undef FUNCTION + +#endif // __CLC_ATOMIC_CLC_ATOMIC_COMPARE_EXCHANGE_H__ diff --git a/libclc/clc/include/clc/atomic/clc_atomic_dec.h b/libclc/clc/include/clc/atomic/clc_atomic_dec.h new file mode 100644 index 0000000000000..ada36ba3ff9b3 --- /dev/null +++ b/libclc/clc/include/clc/atomic/clc_atomic_dec.h @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_ATOMIC_CLC_ATOMIC_DEC_H__ +#define __CLC_ATOMIC_CLC_ATOMIC_DEC_H__ + +#include + +#define FUNCTION __clc_atomic_dec +#define __CLC_NO_VALUE_ARG + +#define __CLC_BODY +#include + +#undef __CLC_NO_VALUE_ARG +#undef FUNCTION + +#endif // __CLC_ATOMIC_CLC_ATOMIC_DEC_H__ diff --git a/libclc/clc/include/clc/atomic/clc_atomic_exchange.h b/libclc/clc/include/clc/atomic/clc_atomic_exchange.h new file mode 100644 index 0000000000000..7e626d4a8830b --- /dev/null +++ b/libclc/clc/include/clc/atomic/clc_atomic_exchange.h @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_ATOMIC_CLC_ATOMIC_EXCHANGE_H__ +#define __CLC_ATOMIC_CLC_ATOMIC_EXCHANGE_H__ + +#include + +#define FUNCTION __clc_atomic_exchange + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#undef FUNCTION + +#endif // __CLC_ATOMIC_CLC_ATOMIC_EXCHANGE_H__ diff --git a/libclc/clc/include/clc/atomic/clc_atomic_fetch_add.h b/libclc/clc/include/clc/atomic/clc_atomic_fetch_add.h new file mode 100644 index 0000000000000..ad0c2eb4607a7 --- /dev/null +++ b/libclc/clc/include/clc/atomic/clc_atomic_fetch_add.h @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_ATOMIC_CLC_ATOMIC_FETCH_ADD_H__ +#define __CLC_ATOMIC_CLC_ATOMIC_FETCH_ADD_H__ + +#include + +#define FUNCTION __clc_atomic_fetch_add + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#undef FUNCTION + +#endif // __CLC_ATOMIC_CLC_ATOMIC_FETCH_ADD_H__ diff --git a/libclc/clc/include/clc/atomic/clc_atomic_fetch_and.h b/libclc/clc/include/clc/atomic/clc_atomic_fetch_and.h new file mode 100644 index 0000000000000..80810c38cbbb8 --- /dev/null +++ b/libclc/clc/include/clc/atomic/clc_atomic_fetch_and.h @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_ATOMIC_CLC_ATOMIC_FETCH_AND_H__ +#define __CLC_ATOMIC_CLC_ATOMIC_FETCH_AND_H__ + +#include + +#define FUNCTION __clc_atomic_fetch_and + +#define __CLC_BODY +#include + +#undef FUNCTION + +#endif // __CLC_ATOMIC_CLC_ATOMIC_FETCH_AND_H__ diff --git a/libclc/clc/include/clc/atomic/clc_atomic_fetch_max.h b/libclc/clc/include/clc/atomic/clc_atomic_fetch_max.h new file mode 100644 index 0000000000000..56f511922e5c7 --- /dev/null +++ b/libclc/clc/include/clc/atomic/clc_atomic_fetch_max.h @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_ATOMIC_CLC_ATOMIC_FETCH_MAX_H__ +#define __CLC_ATOMIC_CLC_ATOMIC_FETCH_MAX_H__ + +#include + +#define FUNCTION __clc_atomic_fetch_max + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#undef FUNCTION + +#endif // __CLC_ATOMIC_CLC_ATOMIC_FETCH_MAX_H__ diff --git a/libclc/clc/include/clc/atomic/clc_atomic_fetch_min.h b/libclc/clc/include/clc/atomic/clc_atomic_fetch_min.h new file mode 100644 index 0000000000000..f17408d28a35d --- /dev/null +++ b/libclc/clc/include/clc/atomic/clc_atomic_fetch_min.h @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_ATOMIC_CLC_ATOMIC_FETCH_MIN_H__ +#define __CLC_ATOMIC_CLC_ATOMIC_FETCH_MIN_H__ + +#include + +#define FUNCTION __clc_atomic_fetch_min + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#undef FUNCTION + +#endif // __CLC_ATOMIC_CLC_ATOMIC_FETCH_MIN_H__ diff --git a/libclc/clc/include/clc/atomic/clc_atomic_fetch_or.h b/libclc/clc/include/clc/atomic/clc_atomic_fetch_or.h new file mode 100644 index 0000000000000..b82069e6f960e --- /dev/null +++ b/libclc/clc/include/clc/atomic/clc_atomic_fetch_or.h @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_ATOMIC_CLC_ATOMIC_FETCH_OR_H__ +#define __CLC_ATOMIC_CLC_ATOMIC_FETCH_OR_H__ + +#include + +#define FUNCTION __clc_atomic_fetch_or + +#define __CLC_BODY +#include + +#undef FUNCTION + +#endif // __CLC_ATOMIC_CLC_ATOMIC_FETCH_OR_H__ diff --git a/libclc/clc/include/clc/atomic/clc_atomic_fetch_sub.h b/libclc/clc/include/clc/atomic/clc_atomic_fetch_sub.h new file mode 100644 index 0000000000000..6cfd224629d60 --- /dev/null +++ b/libclc/clc/include/clc/atomic/clc_atomic_fetch_sub.h @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_ATOMIC_CLC_ATOMIC_FETCH_SUB_H__ +#define __CLC_ATOMIC_CLC_ATOMIC_FETCH_SUB_H__ + +#include + +#define FUNCTION __clc_atomic_fetch_sub + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#undef FUNCTION + +#endif // __CLC_ATOMIC_CLC_ATOMIC_FETCH_SUB_H__ diff --git a/libclc/clc/include/clc/atomic/clc_atomic_fetch_xor.h b/libclc/clc/include/clc/atomic/clc_atomic_fetch_xor.h new file mode 100644 index 0000000000000..b007b47a9369d --- /dev/null +++ b/libclc/clc/include/clc/atomic/clc_atomic_fetch_xor.h @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_ATOMIC_CLC_ATOMIC_FETCH_XOR_H__ +#define __CLC_ATOMIC_CLC_ATOMIC_FETCH_XOR_H__ + +#include + +#define FUNCTION __clc_atomic_fetch_xor + +#define __CLC_BODY +#include + +#undef FUNCTION + +#endif // __CLC_ATOMIC_CLC_ATOMIC_FETCH_XOR_H__ diff --git a/libclc/clc/include/clc/atomic/clc_atomic_inc.h b/libclc/clc/include/clc/atomic/clc_atomic_inc.h new file mode 100644 index 0000000000000..3ddef4a8bf355 --- /dev/null +++ b/libclc/clc/include/clc/atomic/clc_atomic_inc.h @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_ATOMIC_CLC_ATOMIC_INC_H__ +#define __CLC_ATOMIC_CLC_ATOMIC_INC_H__ + +#include + +#define FUNCTION __clc_atomic_inc +#define __CLC_NO_VALUE_ARG + +#define __CLC_BODY +#include + +#undef __CLC_NO_VALUE_ARG +#undef FUNCTION + +#endif // __CLC_ATOMIC_CLC_ATOMIC_INC_H__ diff --git a/libclc/clc/include/clc/atomic/clc_atomic_load.h b/libclc/clc/include/clc/atomic/clc_atomic_load.h new file mode 100644 index 0000000000000..a4899b34b88a1 --- /dev/null +++ b/libclc/clc/include/clc/atomic/clc_atomic_load.h @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef __CLC_ATOMIC_CLC_ATOMIC_LOAD_H__ +#define __CLC_ATOMIC_CLC_ATOMIC_LOAD_H__ + +#include + +#define FUNCTION __clc_atomic_load +#define __CLC_NO_VALUE_ARG + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#undef __CLC_NO_VALUE_ARG +#undef FUNCTION + +#endif // __CLC_ATOMIC_CLC_ATOMIC_LOAD_H__ diff --git a/libclc/clc/include/clc/atomic/clc_atomic_store.h b/libclc/clc/include/clc/atomic/clc_atomic_store.h new file mode 100644 index 0000000000000..6baf0eb7ea32b --- /dev/null +++ b/libclc/clc/include/clc/atomic/clc_atomic_store.h @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef __CLC_ATOMIC_CLC_ATOMIC_STORE_H__ +#define __CLC_ATOMIC_CLC_ATOMIC_STORE_H__ + +#include + +#define FUNCTION __clc_atomic_store +#define __CLC_RETURN_VOID + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#undef __CLC_RETURN_VOID +#undef FUNCTION + +#endif // __CLC_ATOMIC_CLC_ATOMIC_STORE_H__ diff --git a/libclc/clc/include/clc/integer/clc_bit_reverse.h b/libclc/clc/include/clc/integer/clc_bit_reverse.h new file mode 100644 index 0000000000000..c945e326c74fa --- /dev/null +++ b/libclc/clc/include/clc/integer/clc_bit_reverse.h @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_INTEGER_CLC_BIT_REVERSE_H__ +#define __CLC_INTEGER_CLC_BIT_REVERSE_H__ + +#define FUNCTION __clc_bit_reverse +#define __CLC_BODY + +#include + +#undef FUNCTION + +#endif // __CLC_INTEGER_CLC_BIT_REVERSE_H__ diff --git a/libc/include/uchar.h.def b/libclc/clc/include/clc/integer/clc_bitfield_extract_decl.inc similarity index 60% rename from libc/include/uchar.h.def rename to libclc/clc/include/clc/integer/clc_bitfield_extract_decl.inc index 31b7fcb73ded6..c93eff08de0bc 100644 --- a/libc/include/uchar.h.def +++ b/libclc/clc/include/clc/integer/clc_bitfield_extract_decl.inc @@ -1,4 +1,4 @@ -//===-- C standard library header uchar.h ---------------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,11 +6,5 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_UCHAR_H -#define LLVM_LIBC_UCHAR_H - -#include "__llvm-libc-common.h" - -%%public_api() - -#endif // LLVM_LIBC_UCHAR_H +_CLC_OVERLOAD _CLC_DECL __RETTYPE FUNCTION(__CLC_GENTYPE base, uint offset, + uint count); diff --git a/libclc/clc/include/clc/integer/clc_bitfield_extract_signed.h b/libclc/clc/include/clc/integer/clc_bitfield_extract_signed.h new file mode 100644 index 0000000000000..9c2e047b8be00 --- /dev/null +++ b/libclc/clc/include/clc/integer/clc_bitfield_extract_signed.h @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_INTEGER_CLC_BITFIELD_EXTRACT_SIGNED_H__ +#define __CLC_INTEGER_CLC_BITFIELD_EXTRACT_SIGNED_H__ + +#include + +#define FUNCTION __clc_bitfield_extract_signed +#define __RETTYPE __CLC_S_GENTYPE + +#define __CLC_BODY +#include + +#undef __RETTYPE +#undef FUNCTION + +#endif // __CLC_INTEGER_CLC_BITFIELD_EXTRACT_SIGNED_H__ diff --git a/libclc/clc/include/clc/integer/clc_bitfield_extract_unsigned.h b/libclc/clc/include/clc/integer/clc_bitfield_extract_unsigned.h new file mode 100644 index 0000000000000..95305a3027e5d --- /dev/null +++ b/libclc/clc/include/clc/integer/clc_bitfield_extract_unsigned.h @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_INTEGER_CLC_BITFIELD_EXTRACT_SIGNED_H__ +#define __CLC_INTEGER_CLC_BITFIELD_EXTRACT_SIGNED_H__ + +#include + +#define FUNCTION __clc_bitfield_extract_unsigned +#define __RETTYPE __CLC_U_GENTYPE + +#define __CLC_BODY +#include + +#undef __RETTYPE +#undef FUNCTION + +#endif // __CLC_INTEGER_CLC_BITFIELD_EXTRACT_SIGNED_H__ diff --git a/libclc/clc/include/clc/integer/clc_bitfield_insert.h b/libclc/clc/include/clc/integer/clc_bitfield_insert.h new file mode 100644 index 0000000000000..f4d36b2ad2d2e --- /dev/null +++ b/libclc/clc/include/clc/integer/clc_bitfield_insert.h @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_INTEGER_CLC_BITFIELD_INSERT_H__ +#define __CLC_INTEGER_CLC_BITFIELD_INSERT_H__ + +#include + +#define FUNCTION __clc_bitfield_insert +#define __CLC_BODY +#include + +#endif // __CLC_INTEGER_CLC_BITFIELD_INSERT_H__ diff --git a/libclc/clc/include/clc/integer/clc_bitfield_insert.inc b/libclc/clc/include/clc/integer/clc_bitfield_insert.inc new file mode 100644 index 0000000000000..22f58bdc09830 --- /dev/null +++ b/libclc/clc/include/clc/integer/clc_bitfield_insert.inc @@ -0,0 +1,11 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +_CLC_OVERLOAD _CLC_DECL __CLC_GENTYPE FUNCTION(__CLC_GENTYPE base, + __CLC_GENTYPE insert, + uint offset, uint count); diff --git a/libclc/clc/include/clc/relational/binary_decl.inc b/libclc/clc/include/clc/relational/binary_decl.inc index bcdf5238b8f58..dc8ec9db7b7da 100644 --- a/libclc/clc/include/clc/relational/binary_decl.inc +++ b/libclc/clc/include/clc/relational/binary_decl.inc @@ -6,4 +6,12 @@ // //===----------------------------------------------------------------------===// -_CLC_OVERLOAD _CLC_DECL __CLC_INTN FUNCTION(__CLC_FLOATN a, __CLC_FLOATN b); +#if __CLC_VECSIZE_OR_1 == 1 +#define __RETTYPE __CLC_INTN +#else +#define __RETTYPE __CLC_BIT_INTN +#endif + +_CLC_OVERLOAD _CLC_DECL __RETTYPE FUNCTION(__CLC_GENTYPE a, __CLC_GENTYPE b); + +#undef __RETTYPE diff --git a/libclc/clc/include/clc/relational/clc_isfinite.h b/libclc/clc/include/clc/relational/clc_isfinite.h index 5e71ec7a0640a..444d733039819 100644 --- a/libclc/clc/include/clc/relational/clc_isfinite.h +++ b/libclc/clc/include/clc/relational/clc_isfinite.h @@ -12,7 +12,7 @@ #define FUNCTION __clc_isfinite #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/clc/include/clc/relational/clc_isgreater.h b/libclc/clc/include/clc/relational/clc_isgreater.h index e2e6911a80cdd..88de46854961d 100644 --- a/libclc/clc/include/clc/relational/clc_isgreater.h +++ b/libclc/clc/include/clc/relational/clc_isgreater.h @@ -12,7 +12,7 @@ #define FUNCTION __clc_isgreater #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/clc/include/clc/relational/clc_isgreaterequal.h b/libclc/clc/include/clc/relational/clc_isgreaterequal.h index 3fe8835aff9d5..42308036f102f 100644 --- a/libclc/clc/include/clc/relational/clc_isgreaterequal.h +++ b/libclc/clc/include/clc/relational/clc_isgreaterequal.h @@ -12,7 +12,7 @@ #define FUNCTION __clc_isgreaterequal #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/clc/include/clc/relational/clc_isless.h b/libclc/clc/include/clc/relational/clc_isless.h index 01384cf6fa4a0..6fdc6c54947c0 100644 --- a/libclc/clc/include/clc/relational/clc_isless.h +++ b/libclc/clc/include/clc/relational/clc_isless.h @@ -12,7 +12,7 @@ #define FUNCTION __clc_isless #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/clc/include/clc/relational/clc_islessequal.h b/libclc/clc/include/clc/relational/clc_islessequal.h index a4b77a451b248..e592287b23099 100644 --- a/libclc/clc/include/clc/relational/clc_islessequal.h +++ b/libclc/clc/include/clc/relational/clc_islessequal.h @@ -12,7 +12,7 @@ #define FUNCTION __clc_islessequal #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/clc/include/clc/relational/clc_islessgreater.h b/libclc/clc/include/clc/relational/clc_islessgreater.h index 9fb6d641bfa14..a2f10707a677d 100644 --- a/libclc/clc/include/clc/relational/clc_islessgreater.h +++ b/libclc/clc/include/clc/relational/clc_islessgreater.h @@ -12,7 +12,7 @@ #define FUNCTION __clc_islessgreater #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/clc/include/clc/relational/clc_isnormal.h b/libclc/clc/include/clc/relational/clc_isnormal.h index d580fed5a7395..2281bc4245d03 100644 --- a/libclc/clc/include/clc/relational/clc_isnormal.h +++ b/libclc/clc/include/clc/relational/clc_isnormal.h @@ -12,7 +12,7 @@ #define FUNCTION __clc_isnormal #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/clc/include/clc/relational/clc_isnotequal.h b/libclc/clc/include/clc/relational/clc_isnotequal.h index 16982fc3c5aaa..c2640fc0899a6 100644 --- a/libclc/clc/include/clc/relational/clc_isnotequal.h +++ b/libclc/clc/include/clc/relational/clc_isnotequal.h @@ -12,7 +12,7 @@ #define FUNCTION __clc_isnotequal #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/clc/include/clc/relational/clc_isordered.h b/libclc/clc/include/clc/relational/clc_isordered.h index 7ba26662105fc..cb9be31311575 100644 --- a/libclc/clc/include/clc/relational/clc_isordered.h +++ b/libclc/clc/include/clc/relational/clc_isordered.h @@ -12,7 +12,7 @@ #define FUNCTION __clc_isordered #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/clc/include/clc/relational/clc_isunordered.h b/libclc/clc/include/clc/relational/clc_isunordered.h index eac158d245191..36d314ff0e1be 100644 --- a/libclc/clc/include/clc/relational/clc_isunordered.h +++ b/libclc/clc/include/clc/relational/clc_isunordered.h @@ -12,7 +12,7 @@ #define FUNCTION __clc_isunordered #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/clc/include/clc/relational/clc_signbit.h b/libclc/clc/include/clc/relational/clc_signbit.h index 892263a09e99c..9e423ab448953 100644 --- a/libclc/clc/include/clc/relational/clc_signbit.h +++ b/libclc/clc/include/clc/relational/clc_signbit.h @@ -12,7 +12,7 @@ #define FUNCTION __clc_signbit #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/clc/include/clc/relational/floatn.inc b/libclc/clc/include/clc/relational/floatn.inc deleted file mode 100644 index 263937f6eef6f..0000000000000 --- a/libclc/clc/include/clc/relational/floatn.inc +++ /dev/null @@ -1,132 +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 -// -//===----------------------------------------------------------------------===// - -#include -#include - -#define __CLC_FLOATN float -#define __CLC_INTN int -#include __CLC_BODY -#undef __CLC_INTN -#undef __CLC_FLOATN - -#define __CLC_FLOATN float2 -#define __CLC_INTN int2 -#include __CLC_BODY -#undef __CLC_INTN -#undef __CLC_FLOATN - -#define __CLC_FLOATN float3 -#define __CLC_INTN int3 -#include __CLC_BODY -#undef __CLC_INTN -#undef __CLC_FLOATN - -#define __CLC_FLOATN float4 -#define __CLC_INTN int4 -#include __CLC_BODY -#undef __CLC_INTN -#undef __CLC_FLOATN - -#define __CLC_FLOATN float8 -#define __CLC_INTN int8 -#include __CLC_BODY -#undef __CLC_INTN -#undef __CLC_FLOATN - -#define __CLC_FLOATN float16 -#define __CLC_INTN int16 -#include __CLC_BODY -#undef __CLC_INTN -#undef __CLC_FLOATN - -#undef __CLC_FLOAT -#undef __CLC_INT - -#ifdef cl_khr_fp64 -#pragma OPENCL EXTENSION cl_khr_fp64 : enable - -#define __CLC_FLOATN double -#define __CLC_INTN int -#include __CLC_BODY -#undef __CLC_INTN -#undef __CLC_FLOATN - -#define __CLC_FLOATN double2 -#define __CLC_INTN long2 -#include __CLC_BODY -#undef __CLC_INTN -#undef __CLC_FLOATN - -#define __CLC_FLOATN double3 -#define __CLC_INTN long3 -#include __CLC_BODY -#undef __CLC_INTN -#undef __CLC_FLOATN - -#define __CLC_FLOATN double4 -#define __CLC_INTN long4 -#include __CLC_BODY -#undef __CLC_INTN -#undef __CLC_FLOATN - -#define __CLC_FLOATN double8 -#define __CLC_INTN long8 -#include __CLC_BODY -#undef __CLC_INTN -#undef __CLC_FLOATN - -#define __CLC_FLOATN double16 -#define __CLC_INTN long16 -#include __CLC_BODY -#undef __CLC_INTN -#undef __CLC_FLOATN - -#endif -#ifdef cl_khr_fp16 -#pragma OPENCL EXTENSION cl_khr_fp16 : enable - -#define __CLC_FLOATN half -#define __CLC_INTN int -#include __CLC_BODY -#undef __CLC_INTN -#undef __CLC_FLOATN - -#define __CLC_FLOATN half2 -#define __CLC_INTN short2 -#include __CLC_BODY -#undef __CLC_INTN -#undef __CLC_FLOATN - -#define __CLC_FLOATN half3 -#define __CLC_INTN short3 -#include __CLC_BODY -#undef __CLC_INTN -#undef __CLC_FLOATN - -#define __CLC_FLOATN half4 -#define __CLC_INTN short4 -#include __CLC_BODY -#undef __CLC_INTN -#undef __CLC_FLOATN - -#define __CLC_FLOATN half8 -#define __CLC_INTN short8 -#include __CLC_BODY -#undef __CLC_INTN -#undef __CLC_FLOATN - -#define __CLC_FLOATN half16 -#define __CLC_INTN short16 -#include __CLC_BODY -#undef __CLC_INTN -#undef __CLC_FLOATN - -#endif - -#undef __CLC_BODY diff --git a/libclc/clc/include/clc/relational/unary_decl.inc b/libclc/clc/include/clc/relational/unary_decl.inc index b9fb36c905469..cc3f2d065529b 100644 --- a/libclc/clc/include/clc/relational/unary_decl.inc +++ b/libclc/clc/include/clc/relational/unary_decl.inc @@ -6,4 +6,12 @@ // //===----------------------------------------------------------------------===// -_CLC_OVERLOAD _CLC_DECL __CLC_INTN FUNCTION(__CLC_FLOATN x); +#if __CLC_VECSIZE_OR_1 == 1 +#define __RETTYPE __CLC_INTN +#else +#define __RETTYPE __CLC_BIT_INTN +#endif + +_CLC_OVERLOAD _CLC_DECL __RETTYPE FUNCTION(__CLC_GENTYPE x); + +#undef __RETTYPE diff --git a/libclc/clc/lib/generic/SOURCES b/libclc/clc/lib/generic/SOURCES index bf8736a726315..ee4f771799e8e 100644 --- a/libclc/clc/lib/generic/SOURCES +++ b/libclc/clc/lib/generic/SOURCES @@ -1,4 +1,17 @@ async/clc_prefetch.cl +atomic/clc_atomic_compare_exchange.cl +atomic/clc_atomic_dec.cl +atomic/clc_atomic_exchange.cl +atomic/clc_atomic_fetch_add.cl +atomic/clc_atomic_fetch_and.cl +atomic/clc_atomic_fetch_max.cl +atomic/clc_atomic_fetch_min.cl +atomic/clc_atomic_fetch_or.cl +atomic/clc_atomic_fetch_sub.cl +atomic/clc_atomic_fetch_xor.cl +atomic/clc_atomic_inc.cl +atomic/clc_atomic_load.cl +atomic/clc_atomic_store.cl common/clc_degrees.cl common/clc_radians.cl common/clc_sign.cl @@ -15,6 +28,10 @@ geometric/clc_normalize.cl integer/clc_abs.cl integer/clc_abs_diff.cl integer/clc_add_sat.cl +integer/clc_bitfield_extract_signed.cl +integer/clc_bitfield_extract_unsigned.cl +integer/clc_bitfield_insert.cl +integer/clc_bit_reverse.cl integer/clc_clz.cl integer/clc_ctz.cl integer/clc_hadd.cl diff --git a/libclc/clc/lib/generic/atomic/clc_atomic_compare_exchange.cl b/libclc/clc/lib/generic/atomic/clc_atomic_compare_exchange.cl new file mode 100644 index 0000000000000..796dedcef3857 --- /dev/null +++ b/libclc/clc/lib/generic/atomic/clc_atomic_compare_exchange.cl @@ -0,0 +1,15 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include diff --git a/libclc/clc/lib/generic/atomic/clc_atomic_compare_exchange.inc b/libclc/clc/lib/generic/atomic/clc_atomic_compare_exchange.inc new file mode 100644 index 0000000000000..32ff9b45b769e --- /dev/null +++ b/libclc/clc/lib/generic/atomic/clc_atomic_compare_exchange.inc @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifdef __CLC_SCALAR + +#if defined(__SPIR32__) || defined(CLC_NVPTX) +#if (defined(__CLC_FPSIZE) && __CLC_FPSIZE <= 32) || \ + (defined(__CLC_GENSIZE) && (__CLC_GENSIZE == 32)) +#define __CLC_HAS_ATOMIC +#endif +#else // defined(__SPIR32__) || defined(CLC_NVPTX) +#if defined(__CLC_FPSIZE) || (__CLC_GENSIZE >= 32) +#define __CLC_HAS_ATOMIC +#endif +#endif // defined(__SPIR32__) || defined(CLC_NVPTX) + +#ifdef __CLC_HAS_ATOMIC + +#ifdef __CLC_FPSIZE + +#define __CLC_DEFINE_ATOMIC(ADDRSPACE) \ + _CLC_OVERLOAD _CLC_DECL __CLC_GENTYPE __clc_atomic_compare_exchange( \ + volatile ADDRSPACE __CLC_GENTYPE *Ptr, __CLC_GENTYPE Comparator, \ + __CLC_GENTYPE Value, int MemoryOrderEqual, int MemoryOrderUnequal, \ + int MemoryScope) { \ + __CLC_U_GENTYPE Comp = __CLC_AS_U_GENTYPE(Comparator); \ + __scoped_atomic_compare_exchange_n( \ + (ADDRSPACE __CLC_U_GENTYPE *)Ptr, &Comp, __CLC_AS_U_GENTYPE(Value), \ + false, MemoryOrderEqual, MemoryOrderUnequal, MemoryScope); \ + return __CLC_AS_GENTYPE(Comp); \ + } + +#else + +#define __CLC_DEFINE_ATOMIC(ADDRSPACE) \ + _CLC_OVERLOAD _CLC_DECL __CLC_GENTYPE __clc_atomic_compare_exchange( \ + volatile ADDRSPACE __CLC_GENTYPE *Ptr, __CLC_GENTYPE Comparator, \ + __CLC_GENTYPE Value, int MemoryOrderEqual, int MemoryOrderUnequal, \ + int MemoryScope) { \ + __scoped_atomic_compare_exchange_n(Ptr, &Comparator, Value, false, \ + MemoryOrderEqual, MemoryOrderUnequal, \ + MemoryScope); \ + return Comparator; \ + } + +#endif // __CLC_FPSIZE + +__CLC_DEFINE_ATOMIC(global) +__CLC_DEFINE_ATOMIC(local) +#if _CLC_GENERIC_AS_SUPPORTED +__CLC_DEFINE_ATOMIC() +#endif + +#undef __CLC_DEFINE_ATOMIC + +#endif // __CLC_HAS_ATOMIC +#undef __CLC_HAS_ATOMIC + +#endif // __CLC_SCALAR diff --git a/libclc/clc/lib/generic/atomic/clc_atomic_dec.cl b/libclc/clc/lib/generic/atomic/clc_atomic_dec.cl new file mode 100644 index 0000000000000..f35a9624fd013 --- /dev/null +++ b/libclc/clc/lib/generic/atomic/clc_atomic_dec.cl @@ -0,0 +1,16 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +#define FUNCTION __clc_atomic_dec +#define __IMPL_FUNCTION __scoped_atomic_fetch_add +#define __CLC_INC_DEC + +#define __CLC_BODY +#include diff --git a/libclc/clc/lib/generic/atomic/clc_atomic_def.inc b/libclc/clc/lib/generic/atomic/clc_atomic_def.inc new file mode 100644 index 0000000000000..2c45f49f60848 --- /dev/null +++ b/libclc/clc/lib/generic/atomic/clc_atomic_def.inc @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifdef __CLC_SCALAR + +#if defined(__SPIR32__) || defined(CLC_NVPTX) +#if (defined(__CLC_FPSIZE) && __CLC_FPSIZE <= 32) || \ + (defined(__CLC_GENSIZE) && (__CLC_GENSIZE == 32)) +#define __CLC_HAS_ATOMIC +#endif +#else // defined(__SPIR32__) || defined(CLC_NVPTX) +#if defined(__CLC_FPSIZE) || (__CLC_GENSIZE >= 32) +#define __CLC_HAS_ATOMIC +#endif +#endif // defined(__SPIR32__) || defined(CLC_NVPTX) + +#ifdef __CLC_HAS_ATOMIC + +#ifndef __CLC_PTR_CASTTYPE +#define __CLC_PTR_CASTTYPE __CLC_GENTYPE +#endif + +#ifndef __CLC_AS_RETTYPE +#define __CLC_AS_RETTYPE(x) x +#endif + +#ifdef __CLC_NO_VALUE_ARG +#define __CLC_DEFINE_ATOMIC(ADDRSPACE) \ + _CLC_OVERLOAD _CLC_DECL __CLC_GENTYPE FUNCTION( \ + volatile ADDRSPACE __CLC_GENTYPE *Ptr, int MemoryOrder, \ + int MemoryScope) { \ + return __CLC_AS_RETTYPE(__IMPL_FUNCTION( \ + (ADDRSPACE __CLC_PTR_CASTTYPE *)Ptr, MemoryOrder, MemoryScope)); \ + } +#elif defined(__CLC_INC_DEC) +#define __CLC_DEFINE_ATOMIC(ADDRSPACE) \ + _CLC_OVERLOAD _CLC_DECL __CLC_GENTYPE FUNCTION( \ + volatile ADDRSPACE __CLC_GENTYPE *Ptr, int MemoryOrder, \ + int MemoryScope) { \ + return __CLC_AS_RETTYPE( \ + __IMPL_FUNCTION((ADDRSPACE __CLC_PTR_CASTTYPE *)Ptr, (__CLC_GENTYPE)1, \ + MemoryOrder, MemoryScope)); \ + } +#elif defined(__CLC_RETURN_VOID) +#define __CLC_DEFINE_ATOMIC(ADDRSPACE) \ + _CLC_OVERLOAD _CLC_DECL void FUNCTION(volatile ADDRSPACE __CLC_GENTYPE *Ptr, \ + __CLC_GENTYPE Value, int MemoryOrder, \ + int MemoryScope) { \ + __IMPL_FUNCTION((ADDRSPACE __CLC_PTR_CASTTYPE *)Ptr, Value, MemoryOrder, \ + MemoryScope); \ + } +#else +#define __CLC_DEFINE_ATOMIC(ADDRSPACE) \ + _CLC_OVERLOAD _CLC_DECL __CLC_GENTYPE FUNCTION( \ + volatile ADDRSPACE __CLC_GENTYPE *Ptr, __CLC_GENTYPE Value, \ + int MemoryOrder, int MemoryScope) { \ + return __CLC_AS_RETTYPE( \ + __IMPL_FUNCTION((ADDRSPACE __CLC_PTR_CASTTYPE *)Ptr, Value, \ + MemoryOrder, MemoryScope)); \ + } +#endif + +__CLC_DEFINE_ATOMIC(global) +__CLC_DEFINE_ATOMIC(local) +#if _CLC_GENERIC_AS_SUPPORTED +__CLC_DEFINE_ATOMIC() +#endif + +#undef __CLC_DEFINE_ATOMIC + +#endif // __CLC_HAS_ATOMIC +#undef __CLC_HAS_ATOMIC + +#endif // __CLC_SCALAR diff --git a/libclc/clc/lib/generic/atomic/clc_atomic_exchange.cl b/libclc/clc/lib/generic/atomic/clc_atomic_exchange.cl new file mode 100644 index 0000000000000..52fd11afed6a2 --- /dev/null +++ b/libclc/clc/lib/generic/atomic/clc_atomic_exchange.cl @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +#define FUNCTION __clc_atomic_exchange +#define __IMPL_FUNCTION __scoped_atomic_exchange_n + +#define __CLC_BODY +#include + +#undef __CLC_PTR_CASTTYPE +#undef __CLC_AS_RETTYPE +#define __CLC_PTR_CASTTYPE __CLC_BIT_INTN +#define __CLC_AS_RETTYPE(x) __CLC_AS_GENTYPE(x) + +#define __CLC_BODY +#include diff --git a/libclc/clc/lib/generic/atomic/clc_atomic_fetch_add.cl b/libclc/clc/lib/generic/atomic/clc_atomic_fetch_add.cl new file mode 100644 index 0000000000000..0dc44919627b3 --- /dev/null +++ b/libclc/clc/lib/generic/atomic/clc_atomic_fetch_add.cl @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +#define FUNCTION __clc_atomic_fetch_add +#define __IMPL_FUNCTION __scoped_atomic_fetch_add + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include diff --git a/libc/include/dlfcn.h.def b/libclc/clc/lib/generic/atomic/clc_atomic_fetch_and.cl similarity index 52% rename from libc/include/dlfcn.h.def rename to libclc/clc/lib/generic/atomic/clc_atomic_fetch_and.cl index 31395871c6b97..ec89738bc0f62 100644 --- a/libc/include/dlfcn.h.def +++ b/libclc/clc/lib/generic/atomic/clc_atomic_fetch_and.cl @@ -1,4 +1,4 @@ -//===-- C standard library header dlfcn.h ---------------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,12 +6,10 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_DLFCN_H -#define LLVM_LIBC_DLFCN_H - -#include "__llvm-libc-common.h" -#include "llvm-libc-macros/dlfcn-macros.h" +#include -%%public_api() +#define FUNCTION __clc_atomic_fetch_and +#define __IMPL_FUNCTION __scoped_atomic_fetch_and -#endif // LLVM_LIBC_DLFCN_H +#define __CLC_BODY +#include diff --git a/libclc/clc/lib/generic/atomic/clc_atomic_fetch_max.cl b/libclc/clc/lib/generic/atomic/clc_atomic_fetch_max.cl new file mode 100644 index 0000000000000..0acac711aa96d --- /dev/null +++ b/libclc/clc/lib/generic/atomic/clc_atomic_fetch_max.cl @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +#define FUNCTION __clc_atomic_fetch_max +#define __IMPL_FUNCTION __scoped_atomic_fetch_max + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include diff --git a/libclc/clc/lib/generic/atomic/clc_atomic_fetch_min.cl b/libclc/clc/lib/generic/atomic/clc_atomic_fetch_min.cl new file mode 100644 index 0000000000000..7a098588ec005 --- /dev/null +++ b/libclc/clc/lib/generic/atomic/clc_atomic_fetch_min.cl @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +#define FUNCTION __clc_atomic_fetch_min +#define __IMPL_FUNCTION __scoped_atomic_fetch_min + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include diff --git a/libc/include/search.h.def b/libclc/clc/lib/generic/atomic/clc_atomic_fetch_or.cl similarity index 53% rename from libc/include/search.h.def rename to libclc/clc/lib/generic/atomic/clc_atomic_fetch_or.cl index 6301ba7b656ce..e0f48fa408350 100644 --- a/libc/include/search.h.def +++ b/libclc/clc/lib/generic/atomic/clc_atomic_fetch_or.cl @@ -1,4 +1,4 @@ -//===-- POSIX header search.h ---------------------------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,13 +6,10 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_SEARCH_H -#define LLVM_LIBC_SEARCH_H - -#include "__llvm-libc-common.h" -#define __need_size_t -#include +#include -%%public_api() +#define FUNCTION __clc_atomic_fetch_or +#define __IMPL_FUNCTION __scoped_atomic_fetch_or -#endif // LLVM_LIBC_SEARCH_H +#define __CLC_BODY +#include diff --git a/libclc/clc/lib/generic/atomic/clc_atomic_fetch_sub.cl b/libclc/clc/lib/generic/atomic/clc_atomic_fetch_sub.cl new file mode 100644 index 0000000000000..a4c2c1da1555c --- /dev/null +++ b/libclc/clc/lib/generic/atomic/clc_atomic_fetch_sub.cl @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +#define FUNCTION __clc_atomic_fetch_sub +#define __IMPL_FUNCTION __scoped_atomic_fetch_sub + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include diff --git a/libc/include/setjmp.h.def b/libclc/clc/lib/generic/atomic/clc_atomic_fetch_xor.cl similarity index 52% rename from libc/include/setjmp.h.def rename to libclc/clc/lib/generic/atomic/clc_atomic_fetch_xor.cl index 670bc1ac0fe24..4424a298178fd 100644 --- a/libc/include/setjmp.h.def +++ b/libclc/clc/lib/generic/atomic/clc_atomic_fetch_xor.cl @@ -1,4 +1,4 @@ -//===-- C standard library header setjmp.h --------------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,11 +6,10 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_SETJMP_H -#define LLVM_LIBC_SETJMP_H - -#include "__llvm-libc-common.h" +#include -%%public_api() +#define FUNCTION __clc_atomic_fetch_xor +#define __IMPL_FUNCTION __scoped_atomic_fetch_xor -#endif // LLVM_LIBC_SETJMP_H +#define __CLC_BODY +#include diff --git a/libclc/clc/lib/generic/atomic/clc_atomic_inc.cl b/libclc/clc/lib/generic/atomic/clc_atomic_inc.cl new file mode 100644 index 0000000000000..019aa8d9d6dd8 --- /dev/null +++ b/libclc/clc/lib/generic/atomic/clc_atomic_inc.cl @@ -0,0 +1,16 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +#define FUNCTION __clc_atomic_inc +#define __IMPL_FUNCTION __scoped_atomic_fetch_sub +#define __CLC_INC_DEC + +#define __CLC_BODY +#include diff --git a/libclc/clc/lib/generic/atomic/clc_atomic_load.cl b/libclc/clc/lib/generic/atomic/clc_atomic_load.cl new file mode 100644 index 0000000000000..1f083073e43ff --- /dev/null +++ b/libclc/clc/lib/generic/atomic/clc_atomic_load.cl @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +#define FUNCTION __clc_atomic_load +#define __IMPL_FUNCTION __scoped_atomic_load_n +#define __CLC_NO_VALUE_ARG + +#define __CLC_BODY +#include + +#undef __CLC_PTR_CASTTYPE +#undef __CLC_AS_RETTYPE +#define __CLC_PTR_CASTTYPE __CLC_BIT_INTN +#define __CLC_AS_RETTYPE(x) __CLC_AS_GENTYPE(x) + +#define __CLC_BODY +#include diff --git a/libclc/clc/lib/generic/atomic/clc_atomic_store.cl b/libclc/clc/lib/generic/atomic/clc_atomic_store.cl new file mode 100644 index 0000000000000..8fd165b9a83b8 --- /dev/null +++ b/libclc/clc/lib/generic/atomic/clc_atomic_store.cl @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +#define FUNCTION __clc_atomic_store +#define __IMPL_FUNCTION __scoped_atomic_store_n +#define __CLC_RETURN_VOID + +#define __CLC_BODY +#include + +#undef __CLC_PTR_CASTTYPE +#define __CLC_PTR_CASTTYPE __CLC_BIT_INTN + +#define __CLC_BODY +#include diff --git a/libclc/clc/lib/generic/integer/clc_bit_reverse.cl b/libclc/clc/lib/generic/integer/clc_bit_reverse.cl new file mode 100644 index 0000000000000..439957383f583 --- /dev/null +++ b/libclc/clc/lib/generic/integer/clc_bit_reverse.cl @@ -0,0 +1,15 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +#define FUNCTION __clc_bit_reverse +#define __IMPL_FUNCTION(x) __builtin_elementwise_bitreverse +#define __CLC_BODY + +#include diff --git a/libc/include/dirent.h.def b/libclc/clc/lib/generic/integer/clc_bitfield_extract_signed.cl similarity index 59% rename from libc/include/dirent.h.def rename to libclc/clc/lib/generic/integer/clc_bitfield_extract_signed.cl index 6786578fbd067..d779ed6a43593 100644 --- a/libc/include/dirent.h.def +++ b/libclc/clc/lib/generic/integer/clc_bitfield_extract_signed.cl @@ -1,4 +1,4 @@ -//===-- POSIX header dirent.h ---------------------------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,11 +6,7 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_DIRENT_H -#define LLVM_LIBC_DIRENT_H - -#include "__llvm-libc-common.h" - -%%public_api() +#include -#endif // LLVM_LIBC_DIRENT_H +#define __CLC_BODY +#include diff --git a/libclc/clc/lib/generic/integer/clc_bitfield_extract_signed.inc b/libclc/clc/lib/generic/integer/clc_bitfield_extract_signed.inc new file mode 100644 index 0000000000000..84cae2166f7ce --- /dev/null +++ b/libclc/clc/lib/generic/integer/clc_bitfield_extract_signed.inc @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +_CLC_OVERLOAD _CLC_DEF __CLC_S_GENTYPE +__clc_bitfield_extract_signed(__CLC_GENTYPE base, uint offset, uint count) { + if (count == 0) + return 0; + __CLC_U_GENTYPE x = __CLC_AS_U_GENTYPE(base) + << (__CLC_GENSIZE - offset - count); + // Implement an arithmetic shift right. + __CLC_U_GENTYPE s = -(x >> (__CLC_GENSIZE - 1)); + __CLC_U_GENTYPE result = ((s ^ x) >> (__CLC_GENSIZE - count)) ^ s; + return __CLC_AS_S_GENTYPE(result); +} diff --git a/libc/include/string.h.def b/libclc/clc/lib/generic/integer/clc_bitfield_extract_unsigned.cl similarity index 59% rename from libc/include/string.h.def rename to libclc/clc/lib/generic/integer/clc_bitfield_extract_unsigned.cl index 339d005e43a4f..bf7db401034dc 100644 --- a/libc/include/string.h.def +++ b/libclc/clc/lib/generic/integer/clc_bitfield_extract_unsigned.cl @@ -1,4 +1,4 @@ -//===-- C standard library header string.h --------------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,11 +6,7 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_STRING_H -#define LLVM_LIBC_STRING_H - -#include "__llvm-libc-common.h" - -%%public_api() +#include -#endif // LLVM_LIBC_STRING_H +#define __CLC_BODY +#include diff --git a/libclc/clc/lib/generic/integer/clc_bitfield_extract_unsigned.inc b/libclc/clc/lib/generic/integer/clc_bitfield_extract_unsigned.inc new file mode 100644 index 0000000000000..bc81ce5c98b09 --- /dev/null +++ b/libclc/clc/lib/generic/integer/clc_bitfield_extract_unsigned.inc @@ -0,0 +1,16 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +_CLC_OVERLOAD _CLC_DEF __CLC_U_GENTYPE +__clc_bitfield_extract_unsigned(__CLC_GENTYPE base, uint offset, uint count) { + if (count == 0) + return 0; + __CLC_U_GENTYPE result = __CLC_AS_U_GENTYPE(base) + << (__CLC_GENSIZE - offset - count); + return result >> (__CLC_GENSIZE - count); +} diff --git a/libc/include/spawn.h.def b/libclc/clc/lib/generic/integer/clc_bitfield_insert.cl similarity index 61% rename from libc/include/spawn.h.def rename to libclc/clc/lib/generic/integer/clc_bitfield_insert.cl index a8d7015852868..a40fc804f2187 100644 --- a/libc/include/spawn.h.def +++ b/libclc/clc/lib/generic/integer/clc_bitfield_insert.cl @@ -1,4 +1,4 @@ -//===-- POSIX header spawn.h ----------------------------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,11 +6,7 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_SPAWN_H -#define LLVM_LIBC_SPAWN_H - -#include "__llvm-libc-common.h" - -%%public_api() +#include -#endif // LLVM_LIBC_SPAWN_H +#define __CLC_BODY +#include diff --git a/libclc/clc/lib/generic/integer/clc_bitfield_insert.inc b/libclc/clc/lib/generic/integer/clc_bitfield_insert.inc new file mode 100644 index 0000000000000..ad8dac28750cc --- /dev/null +++ b/libclc/clc/lib/generic/integer/clc_bitfield_insert.inc @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +_CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __clc_bitfield_insert(__CLC_GENTYPE base, + __CLC_GENTYPE insert, + uint offset, + uint count) { + __CLC_U_GENTYPE u_base = __CLC_AS_U_GENTYPE(base); + __CLC_U_GENTYPE u_insert = __CLC_AS_U_GENTYPE(insert); + __CLC_U_GENTYPE mask = (((__CLC_U_GENTYPE)1 << count) - (__CLC_U_GENTYPE)1) + << offset; + mask = count < __CLC_GENSIZE ? mask : ~(__CLC_U_GENTYPE)0; + __CLC_U_GENTYPE result = ((u_insert << offset) & mask) | (u_base & ~mask); + return __CLC_AS_GENTYPE(result); +} diff --git a/libclc/clc/lib/generic/math/clc_native_divide.inc b/libclc/clc/lib/generic/math/clc_native_divide.inc index fdf1794812c5a..dac176fb986bd 100644 --- a/libclc/clc/lib/generic/math/clc_native_divide.inc +++ b/libclc/clc/lib/generic/math/clc_native_divide.inc @@ -8,5 +8,6 @@ _CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __clc_native_divide(__CLC_GENTYPE x, __CLC_GENTYPE y) { + _Pragma("clang fp reciprocal(on)"); return x / y; } diff --git a/libclc/clc/lib/generic/math/clc_native_recip.inc b/libclc/clc/lib/generic/math/clc_native_recip.inc index 57eb35a9522f8..e7246dc08a77c 100644 --- a/libclc/clc/lib/generic/math/clc_native_recip.inc +++ b/libclc/clc/lib/generic/math/clc_native_recip.inc @@ -7,5 +7,6 @@ //===----------------------------------------------------------------------===// _CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __clc_native_recip(__CLC_GENTYPE val) { + _Pragma("clang fp reciprocal(on)"); return 1.0f / val; } diff --git a/libclc/clc/lib/generic/math/clc_native_rsqrt.inc b/libclc/clc/lib/generic/math/clc_native_rsqrt.inc index 7a3b0b2af2721..2b2c4bdada9f9 100644 --- a/libclc/clc/lib/generic/math/clc_native_rsqrt.inc +++ b/libclc/clc/lib/generic/math/clc_native_rsqrt.inc @@ -7,5 +7,6 @@ //===----------------------------------------------------------------------===// _CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __clc_native_rsqrt(__CLC_GENTYPE val) { + _Pragma("clang fp reciprocal(on)"); return 1.0f / __clc_native_sqrt(val); } diff --git a/libclc/clc/lib/generic/math/clc_native_tan.inc b/libclc/clc/lib/generic/math/clc_native_tan.inc index f61a78968a754..f0c6c6d37d2b7 100644 --- a/libclc/clc/lib/generic/math/clc_native_tan.inc +++ b/libclc/clc/lib/generic/math/clc_native_tan.inc @@ -7,5 +7,6 @@ //===----------------------------------------------------------------------===// _CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE __clc_native_tan(__CLC_GENTYPE val) { + _Pragma("clang fp reciprocal(on)"); return __clc_native_sin(val) / __clc_native_cos(val); } diff --git a/libclc/cmake/modules/AddLibclc.cmake b/libclc/cmake/modules/AddLibclc.cmake index 056706ee629cd..dc4b1e8286ec0 100644 --- a/libclc/cmake/modules/AddLibclc.cmake +++ b/libclc/cmake/modules/AddLibclc.cmake @@ -425,17 +425,21 @@ function(add_libclc_builtin_set) WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) endif() - if(CMAKE_HOST_UNIX OR LLVM_USE_SYMLINKS) - set(LIBCLC_LINK_OR_COPY create_symlink) - else() - set(LIBCLC_LINK_OR_COPY copy) - endif() - foreach( a IN LISTS ARG_ALIASES ) + if(CMAKE_HOST_UNIX OR LLVM_USE_SYMLINKS) + cmake_path(RELATIVE_PATH libclc_builtins_lib + BASE_DIRECTORY ${LIBCLC_OUTPUT_LIBRARY_DIR} + OUTPUT_VARIABLE LIBCLC_LINK_OR_COPY_SOURCE) + set(LIBCLC_LINK_OR_COPY create_symlink) + else() + set(LIBCLC_LINK_OR_COPY_SOURCE ${libclc_builtins_lib}) + set(LIBCLC_LINK_OR_COPY copy) + endif() + set( alias_suffix "${a}-${ARG_TRIPLE}.bc" ) add_custom_command( OUTPUT ${LIBCLC_OUTPUT_LIBRARY_DIR}/${alias_suffix} - COMMAND ${CMAKE_COMMAND} -E ${LIBCLC_LINK_OR_COPY} ${libclc_builtins_lib} ${LIBCLC_OUTPUT_LIBRARY_DIR}/${alias_suffix} + COMMAND ${CMAKE_COMMAND} -E ${LIBCLC_LINK_OR_COPY} ${LIBCLC_LINK_OR_COPY_SOURCE} ${LIBCLC_OUTPUT_LIBRARY_DIR}/${alias_suffix} DEPENDS prepare-${obj_suffix} ) add_custom_target( alias-${alias_suffix} ALL diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_add.h b/libclc/opencl/include/clc/opencl/atomic/atomic_add.h index 821ae7aab05bf..50fb99d1362fc 100644 --- a/libclc/opencl/include/clc/opencl/atomic/atomic_add.h +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_add.h @@ -12,6 +12,6 @@ #include #define FUNCTION atomic_add -#include +#include #endif // __CLC_OPENCL_ATOMIC_ATOMIC_ADD_H__ diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_and.h b/libclc/opencl/include/clc/opencl/atomic/atomic_and.h index d10cfed9b581a..8ce328c9739aa 100644 --- a/libclc/opencl/include/clc/opencl/atomic/atomic_and.h +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_and.h @@ -12,6 +12,6 @@ #include #define FUNCTION atomic_and -#include +#include #endif // __CLC_OPENCL_ATOMIC_ATOMIC_AND_H__ diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_compare_exchange_strong.h b/libclc/opencl/include/clc/opencl/atomic/atomic_compare_exchange_strong.h new file mode 100644 index 0000000000000..76eeda7ba3469 --- /dev/null +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_compare_exchange_strong.h @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_OPENCL_ATOMIC_ATOMIC_COMPARE_EXCHANGE_STRONG_H__ +#define __CLC_OPENCL_ATOMIC_ATOMIC_COMPARE_EXCHANGE_STRONG_H__ + +#define FUNCTION atomic_compare_exchange_strong +#define __CLC_COMPARE_EXCHANGE + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#undef __CLC_COMPARE_EXCHANGE +#undef FUNCTION + +#endif // __CLC_OPENCL_ATOMIC_ATOMIC_COMPARE_EXCHANGE_STRONG_H__ diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_compare_exchange_weak.h b/libclc/opencl/include/clc/opencl/atomic/atomic_compare_exchange_weak.h new file mode 100644 index 0000000000000..12788ad03a2d1 --- /dev/null +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_compare_exchange_weak.h @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_OPENCL_ATOMIC_ATOMIC_COMPARE_EXCHANGE_WEAK_H__ +#define __CLC_OPENCL_ATOMIC_ATOMIC_COMPARE_EXCHANGE_WEAK_H__ + +#define FUNCTION atomic_compare_exchange_weak +#define __CLC_COMPARE_EXCHANGE + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#undef __CLC_COMPARE_EXCHANGE +#undef FUNCTION + +#endif // __CLC_OPENCL_ATOMIC_ATOMIC_COMPARE_EXCHANGE_WEAK_H__ diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_decl.inc b/libclc/opencl/include/clc/opencl/atomic/atomic_decl.inc index e060e3aaea161..1b2bf17bd6dfd 100644 --- a/libclc/opencl/include/clc/opencl/atomic/atomic_decl.inc +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_decl.inc @@ -6,17 +6,55 @@ // //===----------------------------------------------------------------------===// -#define __CLC_DECLARE_ATOMIC(ADDRSPACE, TYPE) \ - _CLC_OVERLOAD _CLC_DECL TYPE FUNCTION(volatile ADDRSPACE TYPE *, TYPE); +#ifdef __CLC_SCALAR -#define __CLC_DECLARE_ATOMIC_ADDRSPACE(TYPE) \ - __CLC_DECLARE_ATOMIC(global, TYPE) \ - __CLC_DECLARE_ATOMIC(local, TYPE) +#if defined(__opencl_c_fp64) && (defined(cl_khr_int64_base_atomics) && \ + defined(cl_khr_int64_extended_atomics)) +#define HAVE_64_ATOMIC +#endif +#if defined(__CLC_FPSIZE) && (__CLC_FPSIZE < 64 || defined(HAVE_64_ATOMIC)) +#define HAVE_FP_ATOMIC +#endif +#if defined(__CLC_GENSIZE) && \ + ((__CLC_GENSIZE == 32) || \ + (__CLC_GENSIZE == 64 && defined(HAVE_64_ATOMIC))) +#define HAVE_INT_ATOMIC +#endif +#if defined(HAVE_FP_ATOMIC) || defined(HAVE_INT_ATOMIC) -__CLC_DECLARE_ATOMIC_ADDRSPACE(int) -__CLC_DECLARE_ATOMIC_ADDRSPACE(uint) +#define __CLC_ATOMIC_GENTYPE __CLC_XCONCAT(atomic_, __CLC_GENTYPE) -#undef __CLC_DECLARE_ATOMIC_ADDRSPACE -#undef __CLC_DECLARE_ATOMIC +#ifdef __CLC_NO_VALUE_ARG +#define __CLC_DEFINE_ATOMIC(ADDRSPACE) \ + _CLC_OVERLOAD _CLC_DECL __CLC_GENTYPE FUNCTION( \ + volatile ADDRSPACE __CLC_ATOMIC_GENTYPE *Ptr); +#elif defined(__CLC_RETURN_VOID) +#define __CLC_DEFINE_ATOMIC(ADDRSPACE) \ + _CLC_OVERLOAD _CLC_DECL void FUNCTION( \ + volatile ADDRSPACE __CLC_ATOMIC_GENTYPE *Ptr, __CLC_GENTYPE Value); +#elif defined(__CLC_COMPARE_EXCHANGE) +#define __CLC_DEFINE_ATOMIC(ADDRSPACE) \ + _CLC_OVERLOAD _CLC_DECL __CLC_GENTYPE FUNCTION( \ + volatile ADDRSPACE __CLC_ATOMIC_GENTYPE *Ptr, \ + ADDRSPACE __CLC_GENTYPE *Expected, __CLC_GENTYPE Desired); +#else +#define __CLC_DEFINE_ATOMIC(ADDRSPACE) \ + _CLC_OVERLOAD _CLC_DECL __CLC_GENTYPE FUNCTION( \ + volatile ADDRSPACE __CLC_ATOMIC_GENTYPE *Ptr, __CLC_GENTYPE Value); +#endif -#undef FUNCTION +__CLC_DEFINE_ATOMIC(global) +__CLC_DEFINE_ATOMIC(local) +#if _CLC_GENERIC_AS_SUPPORTED +__CLC_DEFINE_ATOMIC() +#endif + +#undef __CLC_DEFINE_ATOMIC + +#endif // HAVE_FP_ATOMIC || HAVE_INT_ATOMIC + +#undef HAVE_INT_ATOMIC +#undef HAVE_FP_ATOMIC +#undef HAVE_64_ATOMIC + +#endif // __CLC_SCALAR diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_decl_legacy.inc b/libclc/opencl/include/clc/opencl/atomic/atomic_decl_legacy.inc new file mode 100644 index 0000000000000..e060e3aaea161 --- /dev/null +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_decl_legacy.inc @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#define __CLC_DECLARE_ATOMIC(ADDRSPACE, TYPE) \ + _CLC_OVERLOAD _CLC_DECL TYPE FUNCTION(volatile ADDRSPACE TYPE *, TYPE); + +#define __CLC_DECLARE_ATOMIC_ADDRSPACE(TYPE) \ + __CLC_DECLARE_ATOMIC(global, TYPE) \ + __CLC_DECLARE_ATOMIC(local, TYPE) + +__CLC_DECLARE_ATOMIC_ADDRSPACE(int) +__CLC_DECLARE_ATOMIC_ADDRSPACE(uint) + +#undef __CLC_DECLARE_ATOMIC_ADDRSPACE +#undef __CLC_DECLARE_ATOMIC + +#undef FUNCTION diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_exchange.h b/libclc/opencl/include/clc/opencl/atomic/atomic_exchange.h new file mode 100644 index 0000000000000..3949bc13401f2 --- /dev/null +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_exchange.h @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_OPENCL_ATOMIC_ATOMIC_EXCHANGE_H__ +#define __CLC_OPENCL_ATOMIC_ATOMIC_EXCHANGE_H__ + +#define FUNCTION atomic_exchange + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#undef FUNCTION + +#endif // __CLC_OPENCL_ATOMIC_ATOMIC_EXCHANGE_H__ diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_add.h b/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_add.h new file mode 100644 index 0000000000000..972c1fa69fe7b --- /dev/null +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_add.h @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_ADD_H__ +#define __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_ADD_H__ + +#define FUNCTION atomic_fetch_add + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#undef FUNCTION + +#endif // __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_ADD_H__ diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_and.h b/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_and.h new file mode 100644 index 0000000000000..fdac049a74d3f --- /dev/null +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_and.h @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_AND_H__ +#define __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_AND_H__ + +#define FUNCTION atomic_fetch_and + +#define __CLC_BODY +#include + +#undef FUNCTION + +#endif // __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_AND_H__ diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_max.h b/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_max.h new file mode 100644 index 0000000000000..513b60fec2727 --- /dev/null +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_max.h @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_MAX_H__ +#define __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_MAX_H__ + +#define FUNCTION atomic_fetch_max + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#undef FUNCTION + +#endif // __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_MAX_H__ diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_min.h b/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_min.h new file mode 100644 index 0000000000000..c961c4a641656 --- /dev/null +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_min.h @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_MIN_H__ +#define __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_MIN_H__ + +#define FUNCTION atomic_fetch_min + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#undef FUNCTION + +#endif // __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_MIN_H__ diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_or.h b/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_or.h new file mode 100644 index 0000000000000..25923e3647e36 --- /dev/null +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_or.h @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_OR_H__ +#define __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_OR_H__ + +#define FUNCTION atomic_fetch_or + +#define __CLC_BODY +#include + +#undef FUNCTION + +#endif // __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_OR_H__ diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_sub.h b/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_sub.h new file mode 100644 index 0000000000000..b307c30a298b3 --- /dev/null +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_sub.h @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_SUB_H__ +#define __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_SUB_H__ + +#define FUNCTION atomic_fetch_sub + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#undef FUNCTION + +#endif // __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_SUB_H__ diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_xor.h b/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_xor.h new file mode 100644 index 0000000000000..52510d018574d --- /dev/null +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_fetch_xor.h @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_XOR_H__ +#define __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_XOR_H__ + +#define FUNCTION atomic_fetch_xor + +#define __CLC_BODY +#include + +#undef FUNCTION + +#endif // __CLC_OPENCL_ATOMIC_ATOMIC_FETCH_XOR_H__ diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_load.h b/libclc/opencl/include/clc/opencl/atomic/atomic_load.h new file mode 100644 index 0000000000000..3998a4de9452b --- /dev/null +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_load.h @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_OPENCL_ATOMIC_ATOMIC_LOAD_H__ +#define __CLC_OPENCL_ATOMIC_ATOMIC_LOAD_H__ + +#define FUNCTION atomic_load +#define __CLC_NO_VALUE_ARG + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#undef __CLC_NO_VALUE_ARG +#undef FUNCTION + +#endif // __CLC_OPENCL_ATOMIC_ATOMIC_LOAD_H__ diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_max.h b/libclc/opencl/include/clc/opencl/atomic/atomic_max.h index 667fa36f16f9d..6b95ad7e68d94 100644 --- a/libclc/opencl/include/clc/opencl/atomic/atomic_max.h +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_max.h @@ -12,6 +12,6 @@ #include #define FUNCTION atomic_max -#include +#include #endif // __CLC_OPENCL_ATOMIC_ATOMIC_MAX_H__ diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_min.h b/libclc/opencl/include/clc/opencl/atomic/atomic_min.h index 91bb636eec875..c1dfacb40b746 100644 --- a/libclc/opencl/include/clc/opencl/atomic/atomic_min.h +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_min.h @@ -12,6 +12,6 @@ #include #define FUNCTION atomic_min -#include +#include #endif // __CLC_OPENCL_ATOMIC_ATOMIC_MIN_H__ diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_or.h b/libclc/opencl/include/clc/opencl/atomic/atomic_or.h index 5c03fd157a2bc..30c32fe4889d5 100644 --- a/libclc/opencl/include/clc/opencl/atomic/atomic_or.h +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_or.h @@ -12,6 +12,6 @@ #include #define FUNCTION atomic_or -#include +#include #endif // __CLC_OPENCL_ATOMIC_ATOMIC_OR_H__ diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_store.h b/libclc/opencl/include/clc/opencl/atomic/atomic_store.h new file mode 100644 index 0000000000000..4893a5b88df03 --- /dev/null +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_store.h @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_OPENCL_ATOMIC_ATOMIC_STORE_H__ +#define __CLC_OPENCL_ATOMIC_ATOMIC_STORE_H__ + +#define FUNCTION atomic_store +#define __CLC_RETURN_VOID + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#undef __CLC_RETURN_VOID +#undef FUNCTION + +#endif // __CLC_OPENCL_ATOMIC_ATOMIC_STORE_H__ diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_sub.h b/libclc/opencl/include/clc/opencl/atomic/atomic_sub.h index 25ffe9ff4a9b7..1e7ac5505b071 100644 --- a/libclc/opencl/include/clc/opencl/atomic/atomic_sub.h +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_sub.h @@ -12,6 +12,6 @@ #include #define FUNCTION atomic_sub -#include +#include #endif // __CLC_OPENCL_ATOMIC_ATOMIC_SUB_H__ diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_xchg.h b/libclc/opencl/include/clc/opencl/atomic/atomic_xchg.h index 6b4206dedb820..043d7825483e4 100644 --- a/libclc/opencl/include/clc/opencl/atomic/atomic_xchg.h +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_xchg.h @@ -15,6 +15,6 @@ _CLC_OVERLOAD _CLC_DECL float FUNCTION(volatile local float *, float); _CLC_OVERLOAD _CLC_DECL float FUNCTION(volatile global float *, float); -#include +#include #endif // __CLC_OPENCL_ATOMIC_ATOMIC_XCHG_H__ diff --git a/libclc/opencl/include/clc/opencl/atomic/atomic_xor.h b/libclc/opencl/include/clc/opencl/atomic/atomic_xor.h index e94560cb6b9ed..a9bee007b9344 100644 --- a/libclc/opencl/include/clc/opencl/atomic/atomic_xor.h +++ b/libclc/opencl/include/clc/opencl/atomic/atomic_xor.h @@ -12,6 +12,6 @@ #include #define FUNCTION atomic_xor -#include +#include #endif // __CLC_OPENCL_ATOMIC_ATOMIC_XOR_H__ diff --git a/libclc/opencl/include/clc/opencl/integer/bit_reverse.h b/libclc/opencl/include/clc/opencl/integer/bit_reverse.h new file mode 100644 index 0000000000000..46b589557631d --- /dev/null +++ b/libclc/opencl/include/clc/opencl/integer/bit_reverse.h @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef __CLC_OPENCL_INTEGER_BIT_REVERSE_H__ +#define __CLC_OPENCL_INTEGER_BIT_REVERSE_H__ + +#ifdef cl_khr_extended_bit_ops + +#include + +#define FUNCTION bit_reverse +#define __CLC_BODY + +#include + +#undef FUNCTION + +#endif // cl_khr_extended_bit_ops + +#endif // __CLC_OPENCL_INTEGER_BIT_REVERSE_H__ diff --git a/libclc/opencl/include/clc/opencl/integer/bitfield_extract_signed.h b/libclc/opencl/include/clc/opencl/integer/bitfield_extract_signed.h new file mode 100644 index 0000000000000..0a902b2a21d6d --- /dev/null +++ b/libclc/opencl/include/clc/opencl/integer/bitfield_extract_signed.h @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_OPENCL_INTEGER_BITFIELD_EXTRACT_SIGNED_H__ +#define __CLC_OPENCL_INTEGER_BITFIELD_EXTRACT_SIGNED_H__ + +#ifdef cl_khr_extended_bit_ops + +#include + +#define FUNCTION bitfield_extract_signed +#define __RETTYPE __CLC_S_GENTYPE + +#define __CLC_BODY +#include + +#undef __RETTYPE +#undef FUNCTION + +#endif // cl_khr_extended_bit_ops + +#endif // __CLC_OPENCL_INTEGER_BITFIELD_EXTRACT_SIGNED_H__ diff --git a/libclc/opencl/include/clc/opencl/integer/bitfield_extract_unsigned.h b/libclc/opencl/include/clc/opencl/integer/bitfield_extract_unsigned.h new file mode 100644 index 0000000000000..28064c08b113e --- /dev/null +++ b/libclc/opencl/include/clc/opencl/integer/bitfield_extract_unsigned.h @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_OPENCL_INTEGER_BITFIELD_EXTRACT_UNSIGNED_H__ +#define __CLC_OPENCL_INTEGER_BITFIELD_EXTRACT_UNSIGNED_H__ + +#ifdef cl_khr_extended_bit_ops + +#include + +#define FUNCTION bitfield_extract_unsigned +#define __RETTYPE __CLC_U_GENTYPE + +#define __CLC_BODY +#include + +#undef __RETTYPE +#undef FUNCTION + +#endif // cl_khr_extended_bit_ops + +#endif // __CLC_OPENCL_INTEGER_BITFIELD_EXTRACT_UNSIGNED_H__ diff --git a/libclc/opencl/include/clc/opencl/integer/bitfield_insert.h b/libclc/opencl/include/clc/opencl/integer/bitfield_insert.h new file mode 100644 index 0000000000000..e77d7a4f0b957 --- /dev/null +++ b/libclc/opencl/include/clc/opencl/integer/bitfield_insert.h @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// 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 __CLC_OPENCL_INTEGER_BITFIELD_INSERT_H__ +#define __CLC_OPENCL_INTEGER_BITFIELD_INSERT_H__ + +#ifdef cl_khr_extended_bit_ops + +#include + +#define __CLC_BODY +#include + +#undef FUNCTION + +#endif // cl_khr_extended_bit_ops + +#endif // __CLC_OPENCL_INTEGER_BITFIELD_INSERT_H__ diff --git a/libclc/opencl/include/clc/opencl/relational/isfinite.h b/libclc/opencl/include/clc/opencl/relational/isfinite.h index 2548e6acf5109..ac3db6764073a 100644 --- a/libclc/opencl/include/clc/opencl/relational/isfinite.h +++ b/libclc/opencl/include/clc/opencl/relational/isfinite.h @@ -14,7 +14,7 @@ #define FUNCTION isfinite #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/opencl/include/clc/opencl/relational/isgreater.h b/libclc/opencl/include/clc/opencl/relational/isgreater.h index 6dfe6eb810e2a..2230055115bcd 100644 --- a/libclc/opencl/include/clc/opencl/relational/isgreater.h +++ b/libclc/opencl/include/clc/opencl/relational/isgreater.h @@ -14,7 +14,7 @@ #define FUNCTION isgreater #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/opencl/include/clc/opencl/relational/isgreaterequal.h b/libclc/opencl/include/clc/opencl/relational/isgreaterequal.h index 1db2c5d58d062..f99a620dabd78 100644 --- a/libclc/opencl/include/clc/opencl/relational/isgreaterequal.h +++ b/libclc/opencl/include/clc/opencl/relational/isgreaterequal.h @@ -14,7 +14,7 @@ #define FUNCTION isgreaterequal #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/opencl/include/clc/opencl/relational/isless.h b/libclc/opencl/include/clc/opencl/relational/isless.h index 3e2afb32cddf4..74280e543e0b5 100644 --- a/libclc/opencl/include/clc/opencl/relational/isless.h +++ b/libclc/opencl/include/clc/opencl/relational/isless.h @@ -14,7 +14,7 @@ #define FUNCTION isless #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/opencl/include/clc/opencl/relational/islessequal.h b/libclc/opencl/include/clc/opencl/relational/islessequal.h index 978e6a9052c16..dcc26c37b73c1 100644 --- a/libclc/opencl/include/clc/opencl/relational/islessequal.h +++ b/libclc/opencl/include/clc/opencl/relational/islessequal.h @@ -14,7 +14,7 @@ #define FUNCTION islessequal #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/opencl/include/clc/opencl/relational/islessgreater.h b/libclc/opencl/include/clc/opencl/relational/islessgreater.h index 56cce7db20770..15a1eb5577531 100644 --- a/libclc/opencl/include/clc/opencl/relational/islessgreater.h +++ b/libclc/opencl/include/clc/opencl/relational/islessgreater.h @@ -14,7 +14,7 @@ #define FUNCTION islessgreater #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/opencl/include/clc/opencl/relational/isnormal.h b/libclc/opencl/include/clc/opencl/relational/isnormal.h index ee74a990b5eaf..bbb06aad0df2a 100644 --- a/libclc/opencl/include/clc/opencl/relational/isnormal.h +++ b/libclc/opencl/include/clc/opencl/relational/isnormal.h @@ -14,7 +14,7 @@ #define FUNCTION isnormal #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/opencl/include/clc/opencl/relational/isnotequal.h b/libclc/opencl/include/clc/opencl/relational/isnotequal.h index 7cf94e3ceec5f..c13aca8ef4be8 100644 --- a/libclc/opencl/include/clc/opencl/relational/isnotequal.h +++ b/libclc/opencl/include/clc/opencl/relational/isnotequal.h @@ -14,7 +14,7 @@ #define FUNCTION isnotequal #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/opencl/include/clc/opencl/relational/isordered.h b/libclc/opencl/include/clc/opencl/relational/isordered.h index ad9770bd627f2..ea4ba3fa6fe8d 100644 --- a/libclc/opencl/include/clc/opencl/relational/isordered.h +++ b/libclc/opencl/include/clc/opencl/relational/isordered.h @@ -14,7 +14,7 @@ #define FUNCTION isordered #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/opencl/include/clc/opencl/relational/isunordered.h b/libclc/opencl/include/clc/opencl/relational/isunordered.h index 01d2f53837317..76bf85604d1c7 100644 --- a/libclc/opencl/include/clc/opencl/relational/isunordered.h +++ b/libclc/opencl/include/clc/opencl/relational/isunordered.h @@ -14,7 +14,7 @@ #define FUNCTION isunordered #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/opencl/include/clc/opencl/relational/signbit.h b/libclc/opencl/include/clc/opencl/relational/signbit.h index 29591c0c126a9..6ad6595c7e294 100644 --- a/libclc/opencl/include/clc/opencl/relational/signbit.h +++ b/libclc/opencl/include/clc/opencl/relational/signbit.h @@ -14,7 +14,7 @@ #define FUNCTION signbit #define __CLC_BODY -#include +#include #undef FUNCTION diff --git a/libclc/opencl/lib/generic/SOURCES b/libclc/opencl/lib/generic/SOURCES index 46ce6d6e36c24..61757efbcaad7 100644 --- a/libclc/opencl/lib/generic/SOURCES +++ b/libclc/opencl/lib/generic/SOURCES @@ -8,24 +8,36 @@ atomic/atom_add.cl atomic/atom_and.cl atomic/atom_cmpxchg.cl atomic/atom_dec.cl -atomic/atom_inc.cl -atomic/atom_max.cl -atomic/atom_min.cl -atomic/atom_or.cl -atomic/atom_sub.cl -atomic/atom_xchg.cl -atomic/atom_xor.cl atomic/atomic_add.cl atomic/atomic_and.cl atomic/atomic_cmpxchg.cl +atomic/atomic_compare_exchange_strong.cl +atomic/atomic_compare_exchange_weak.cl atomic/atomic_dec.cl +atomic/atomic_exchange.cl +atomic/atomic_fetch_add.cl +atomic/atomic_fetch_and.cl +atomic/atomic_fetch_max.cl +atomic/atomic_fetch_min.cl +atomic/atomic_fetch_or.cl +atomic/atomic_fetch_sub.cl +atomic/atomic_fetch_xor.cl atomic/atomic_inc.cl +atomic/atomic_load.cl atomic/atomic_max.cl atomic/atomic_min.cl atomic/atomic_or.cl +atomic/atomic_store.cl atomic/atomic_sub.cl atomic/atomic_xchg.cl atomic/atomic_xor.cl +atomic/atom_inc.cl +atomic/atom_max.cl +atomic/atom_min.cl +atomic/atom_or.cl +atomic/atom_sub.cl +atomic/atom_xchg.cl +atomic/atom_xor.cl common/degrees.cl common/mix.cl common/radians.cl @@ -43,6 +55,10 @@ geometric/normalize.cl integer/abs.cl integer/abs_diff.cl integer/add_sat.cl +integer/bitfield_extract_signed.cl +integer/bitfield_extract_unsigned.cl +integer/bitfield_insert.cl +integer/bit_reverse.cl integer/clz.cl integer/ctz.cl integer/hadd.cl diff --git a/libclc/opencl/lib/generic/atomic/atomic_compare_exchange_strong.cl b/libclc/opencl/lib/generic/atomic/atomic_compare_exchange_strong.cl new file mode 100644 index 0000000000000..422c03f292071 --- /dev/null +++ b/libclc/opencl/lib/generic/atomic/atomic_compare_exchange_strong.cl @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#if defined(__opencl_c_atomic_order_seq_cst) && \ + defined(__opencl_c_atomic_scope_device) + +#include +#include + +#define FUNCTION atomic_compare_exchange_strong +#define __CLC_COMPARE_EXCHANGE + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#endif // defined(__opencl_c_atomic_order_seq_cst) && + // defined(__opencl_c_atomic_scope_device) diff --git a/libclc/opencl/lib/generic/atomic/atomic_compare_exchange_weak.cl b/libclc/opencl/lib/generic/atomic/atomic_compare_exchange_weak.cl new file mode 100644 index 0000000000000..8a6b3c4f0110e --- /dev/null +++ b/libclc/opencl/lib/generic/atomic/atomic_compare_exchange_weak.cl @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#if defined(__opencl_c_atomic_order_seq_cst) && \ + defined(__opencl_c_atomic_scope_device) + +#include +#include + +#define FUNCTION atomic_compare_exchange_weak +#define __CLC_COMPARE_EXCHANGE + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#endif // defined(__opencl_c_atomic_order_seq_cst) && + // defined(__opencl_c_atomic_scope_device) diff --git a/libclc/opencl/lib/generic/atomic/atomic_dec.cl b/libclc/opencl/lib/generic/atomic/atomic_dec.cl index 6f18cdf13428a..6de55bc0b9845 100644 --- a/libclc/opencl/lib/generic/atomic/atomic_dec.cl +++ b/libclc/opencl/lib/generic/atomic/atomic_dec.cl @@ -6,15 +6,11 @@ // //===----------------------------------------------------------------------===// +#include #include -#define IMPL(TYPE, AS) \ - _CLC_OVERLOAD _CLC_DEF TYPE atomic_dec(volatile AS TYPE *p) { \ - return __sync_fetch_and_sub(p, (TYPE)1); \ - } +#define FUNCTION atomic_dec +#define __IMPL_FUNCTION __clc_atomic_dec -IMPL(int, global) -IMPL(unsigned int, global) -IMPL(int, local) -IMPL(unsigned int, local) -#undef IMPL +#define __CLC_BODY +#include diff --git a/libclc/opencl/lib/generic/atomic/atomic_def.inc b/libclc/opencl/lib/generic/atomic/atomic_def.inc new file mode 100644 index 0000000000000..ce192bf844938 --- /dev/null +++ b/libclc/opencl/lib/generic/atomic/atomic_def.inc @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifdef __CLC_SCALAR + +#if defined(__opencl_c_fp64) && (defined(cl_khr_int64_base_atomics) && \ + defined(cl_khr_int64_extended_atomics)) +#define HAVE_64_ATOMIC +#endif +#if defined(__CLC_FPSIZE) && (__CLC_FPSIZE < 64 || defined(HAVE_64_ATOMIC) +#define HAVE_FP_ATOMIC +#endif +#if defined(__CLC_GENSIZE) && \ + ((__CLC_GENSIZE == 32) || \ + (__CLC_GENSIZE == 64 && defined(HAVE_64_ATOMIC))) +#define HAVE_INT_ATOMIC +#endif +#if defined(HAVE_FP_ATOMIC) || defined(HAVE_INT_ATOMIC) + +#define __CLC_ATOMIC_GENTYPE __CLC_XCONCAT(atomic_, __CLC_GENTYPE) + +#ifdef __CLC_NO_VALUE_ARG +#define __CLC_DEFINE_ATOMIC(ADDRSPACE) \ + _CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE FUNCTION( \ + volatile ADDRSPACE __CLC_ATOMIC_GENTYPE *Ptr) { \ + return __IMPL_FUNCTION((volatile ADDRSPACE __CLC_GENTYPE *)Ptr, \ + __ATOMIC_SEQ_CST, __MEMORY_SCOPE_DEVICE); \ + } +#elif defined(__CLC_RETURN_VOID) +#define __CLC_DEFINE_ATOMIC(ADDRSPACE) \ + _CLC_OVERLOAD _CLC_DEF void FUNCTION( \ + volatile ADDRSPACE __CLC_ATOMIC_GENTYPE *Ptr, __CLC_GENTYPE Value) { \ + __IMPL_FUNCTION((volatile ADDRSPACE __CLC_GENTYPE *)Ptr, Value, \ + __ATOMIC_SEQ_CST, __MEMORY_SCOPE_DEVICE); \ + } +#elif defined(__CLC_COMPARE_EXCHANGE) +#define __CLC_DEFINE_ATOMIC(ADDRSPACE) \ + _CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE FUNCTION( \ + volatile ADDRSPACE __CLC_ATOMIC_GENTYPE *Ptr, \ + ADDRSPACE __CLC_GENTYPE *Expected, __CLC_GENTYPE Desired) { \ + __CLC_GENTYPE Comparator = *Expected; \ + __CLC_GENTYPE RetValue = __clc_atomic_compare_exchange( \ + (volatile ADDRSPACE __CLC_GENTYPE *)Ptr, Comparator, Desired, \ + __ATOMIC_SEQ_CST, __ATOMIC_RELAXED, __MEMORY_SCOPE_DEVICE); \ + if (Comparator != RetValue) { \ + *Expected = RetValue; \ + return true; \ + } \ + return false; \ + } +#else +#define __CLC_DEFINE_ATOMIC(ADDRSPACE) \ + _CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE FUNCTION( \ + volatile ADDRSPACE __CLC_ATOMIC_GENTYPE *Ptr, __CLC_GENTYPE Value) { \ + return __IMPL_FUNCTION((volatile ADDRSPACE __CLC_GENTYPE *)Ptr, Value, \ + __ATOMIC_SEQ_CST, __MEMORY_SCOPE_DEVICE); \ + } +#endif + +__CLC_DEFINE_ATOMIC(global) +__CLC_DEFINE_ATOMIC(local) +#if _CLC_GENERIC_AS_SUPPORTED +__CLC_DEFINE_ATOMIC() +#endif + +#undef __CLC_DEFINE_ATOMIC + +#endif // HAVE_FP_ATOMIC || HAVE_INT_ATOMIC + +#undef HAVE_INT_ATOMIC +#undef HAVE_FP_ATOMIC +#undef HAVE_64_ATOMIC + +#endif // __CLC_SCALAR diff --git a/libclc/opencl/lib/generic/atomic/atomic_exchange.cl b/libclc/opencl/lib/generic/atomic/atomic_exchange.cl new file mode 100644 index 0000000000000..6dae6c0a77599 --- /dev/null +++ b/libclc/opencl/lib/generic/atomic/atomic_exchange.cl @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#if defined(__opencl_c_atomic_order_seq_cst) && \ + defined(__opencl_c_atomic_scope_device) + +#include +#include + +#define FUNCTION atomic_exchange +#define __IMPL_FUNCTION __clc_atomic_exchange + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#endif // defined(__opencl_c_atomic_order_seq_cst) && + // defined(__opencl_c_atomic_scope_device) diff --git a/libclc/opencl/lib/generic/atomic/atomic_fetch_add.cl b/libclc/opencl/lib/generic/atomic/atomic_fetch_add.cl new file mode 100644 index 0000000000000..bbaa1c2b0dacf --- /dev/null +++ b/libclc/opencl/lib/generic/atomic/atomic_fetch_add.cl @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#if defined(__opencl_c_atomic_order_seq_cst) && \ + defined(__opencl_c_atomic_scope_device) + +#include +#include + +#define FUNCTION atomic_fetch_add +#define __IMPL_FUNCTION __clc_atomic_fetch_add + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#endif // defined(__opencl_c_atomic_order_seq_cst) && + // defined(__opencl_c_atomic_scope_device) diff --git a/libclc/opencl/lib/generic/atomic/atomic_fetch_and.cl b/libclc/opencl/lib/generic/atomic/atomic_fetch_and.cl new file mode 100644 index 0000000000000..73925844c9357 --- /dev/null +++ b/libclc/opencl/lib/generic/atomic/atomic_fetch_and.cl @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#if defined(__opencl_c_atomic_order_seq_cst) && \ + defined(__opencl_c_atomic_scope_device) + +#include +#include + +#define FUNCTION atomic_fetch_and +#define __IMPL_FUNCTION __clc_atomic_fetch_and + +#define __CLC_BODY +#include + +#endif // defined(__opencl_c_atomic_order_seq_cst) && + // defined(__opencl_c_atomic_scope_device) diff --git a/libclc/opencl/lib/generic/atomic/atomic_fetch_max.cl b/libclc/opencl/lib/generic/atomic/atomic_fetch_max.cl new file mode 100644 index 0000000000000..8c8ce11cc575f --- /dev/null +++ b/libclc/opencl/lib/generic/atomic/atomic_fetch_max.cl @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#if defined(__opencl_c_atomic_order_seq_cst) && \ + defined(__opencl_c_atomic_scope_device) + +#include +#include + +#define FUNCTION atomic_fetch_max +#define __IMPL_FUNCTION __clc_atomic_fetch_max + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#endif // defined(__opencl_c_atomic_order_seq_cst) && + // defined(__opencl_c_atomic_scope_device) diff --git a/libclc/opencl/lib/generic/atomic/atomic_fetch_min.cl b/libclc/opencl/lib/generic/atomic/atomic_fetch_min.cl new file mode 100644 index 0000000000000..550459cee32d6 --- /dev/null +++ b/libclc/opencl/lib/generic/atomic/atomic_fetch_min.cl @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#if defined(__opencl_c_atomic_order_seq_cst) && \ + defined(__opencl_c_atomic_scope_device) + +#include +#include + +#define FUNCTION atomic_fetch_min +#define __IMPL_FUNCTION __clc_atomic_fetch_min + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#endif // defined(__opencl_c_atomic_order_seq_cst) && + // defined(__opencl_c_atomic_scope_device) diff --git a/libclc/opencl/lib/generic/atomic/atomic_fetch_or.cl b/libclc/opencl/lib/generic/atomic/atomic_fetch_or.cl new file mode 100644 index 0000000000000..2606ff3c99673 --- /dev/null +++ b/libclc/opencl/lib/generic/atomic/atomic_fetch_or.cl @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#if defined(__opencl_c_atomic_order_seq_cst) && \ + defined(__opencl_c_atomic_scope_device) + +#include +#include + +#define FUNCTION atomic_fetch_or +#define __IMPL_FUNCTION __clc_atomic_fetch_or + +#define __CLC_BODY +#include + +#endif // defined(__opencl_c_atomic_order_seq_cst) && + // defined(__opencl_c_atomic_scope_device) diff --git a/libclc/opencl/lib/generic/atomic/atomic_fetch_sub.cl b/libclc/opencl/lib/generic/atomic/atomic_fetch_sub.cl new file mode 100644 index 0000000000000..33772233bebed --- /dev/null +++ b/libclc/opencl/lib/generic/atomic/atomic_fetch_sub.cl @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#if defined(__opencl_c_atomic_order_seq_cst) && \ + defined(__opencl_c_atomic_scope_device) + +#include +#include + +#define FUNCTION atomic_fetch_sub +#define __IMPL_FUNCTION __clc_atomic_fetch_sub + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#endif // defined(__opencl_c_atomic_order_seq_cst) && + // defined(__opencl_c_atomic_scope_device) diff --git a/libclc/opencl/lib/generic/atomic/atomic_fetch_xor.cl b/libclc/opencl/lib/generic/atomic/atomic_fetch_xor.cl new file mode 100644 index 0000000000000..6f6503e588b6f --- /dev/null +++ b/libclc/opencl/lib/generic/atomic/atomic_fetch_xor.cl @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#if defined(__opencl_c_atomic_order_seq_cst) && \ + defined(__opencl_c_atomic_scope_device) + +#include +#include + +#define FUNCTION atomic_fetch_xor +#define __IMPL_FUNCTION __clc_atomic_fetch_xor + +#define __CLC_BODY +#include + +#endif // defined(__opencl_c_atomic_order_seq_cst) && + // defined(__opencl_c_atomic_scope_device) diff --git a/libclc/opencl/lib/generic/atomic/atomic_inc.cl b/libclc/opencl/lib/generic/atomic/atomic_inc.cl index 13349e5432e5c..a160b2e2370fc 100644 --- a/libclc/opencl/lib/generic/atomic/atomic_inc.cl +++ b/libclc/opencl/lib/generic/atomic/atomic_inc.cl @@ -6,15 +6,11 @@ // //===----------------------------------------------------------------------===// +#include #include -#define IMPL(TYPE, AS) \ - _CLC_OVERLOAD _CLC_DEF TYPE atomic_inc(volatile AS TYPE *p) { \ - return __sync_fetch_and_add(p, (TYPE)1); \ - } +#define FUNCTION atomic_inc +#define __IMPL_FUNCTION __clc_atomic_inc -IMPL(int, global) -IMPL(unsigned int, global) -IMPL(int, local) -IMPL(unsigned int, local) -#undef IMPL +#define __CLC_BODY +#include diff --git a/libclc/opencl/lib/generic/atomic/atomic_inc_dec.inc b/libclc/opencl/lib/generic/atomic/atomic_inc_dec.inc new file mode 100644 index 0000000000000..0bcf300dd284a --- /dev/null +++ b/libclc/opencl/lib/generic/atomic/atomic_inc_dec.inc @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifdef __CLC_SCALAR + +#if __CLC_GENSIZE == 32 + +#define __CLC_DEFINE_ATOMIC(ADDRSPACE) \ + _CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE FUNCTION( \ + volatile ADDRSPACE __CLC_GENTYPE *Ptr) { \ + return __IMPL_FUNCTION(Ptr, __ATOMIC_SEQ_CST, __MEMORY_SCOPE_DEVICE); \ + } + +__CLC_DEFINE_ATOMIC(global) +__CLC_DEFINE_ATOMIC(local) + +#undef __CLC_DEFINE_ATOMIC + +#endif // __CLC_GENSIZE == 32 + +#endif // __CLC_SCALAR diff --git a/libclc/opencl/lib/generic/atomic/atomic_load.cl b/libclc/opencl/lib/generic/atomic/atomic_load.cl new file mode 100644 index 0000000000000..459265473a8c8 --- /dev/null +++ b/libclc/opencl/lib/generic/atomic/atomic_load.cl @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#if defined(__opencl_c_atomic_order_seq_cst) && \ + defined(__opencl_c_atomic_scope_device) + +#include +#include + +#define FUNCTION atomic_load +#define __IMPL_FUNCTION __clc_atomic_load +#define __CLC_NO_VALUE_ARG + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#endif // defined(__opencl_c_atomic_order_seq_cst) && + // defined(__opencl_c_atomic_scope_device) diff --git a/libclc/opencl/lib/generic/atomic/atomic_store.cl b/libclc/opencl/lib/generic/atomic/atomic_store.cl new file mode 100644 index 0000000000000..67f2c8457fc10 --- /dev/null +++ b/libclc/opencl/lib/generic/atomic/atomic_store.cl @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#if defined(__opencl_c_atomic_order_seq_cst) && \ + defined(__opencl_c_atomic_scope_device) + +#include +#include + +#define FUNCTION atomic_store +#define __IMPL_FUNCTION __clc_atomic_store +#define __CLC_RETURN_VOID + +#define __CLC_BODY +#include + +#define __CLC_BODY +#include + +#endif // defined(__opencl_c_atomic_order_seq_cst) && + // defined(__opencl_c_atomic_scope_device) diff --git a/libclc/opencl/lib/generic/integer/bit_reverse.cl b/libclc/opencl/lib/generic/integer/bit_reverse.cl new file mode 100644 index 0000000000000..23181b6b3eba5 --- /dev/null +++ b/libclc/opencl/lib/generic/integer/bit_reverse.cl @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifdef cl_khr_extended_bit_ops + +#include +#include + +#define FUNCTION bit_reverse +#define __CLC_BODY + +#include + +#endif // cl_khr_extended_bit_ops diff --git a/libclc/opencl/lib/generic/integer/bitfield_extract_def.inc b/libclc/opencl/lib/generic/integer/bitfield_extract_def.inc new file mode 100644 index 0000000000000..0262f67732afc --- /dev/null +++ b/libclc/opencl/lib/generic/integer/bitfield_extract_def.inc @@ -0,0 +1,16 @@ +//===----------------------------------------------------------------------===// +// +// 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 __IMPL_FUNCTION +#define __IMPL_FUNCTION(x) __CLC_CONCAT(__clc_, x) +#endif + +_CLC_OVERLOAD _CLC_DEF __RETTYPE FUNCTION(__CLC_GENTYPE base, uint offset, + uint count) { + return __IMPL_FUNCTION(FUNCTION)(base, offset, count); +} diff --git a/libclc/opencl/lib/generic/integer/bitfield_extract_signed.cl b/libclc/opencl/lib/generic/integer/bitfield_extract_signed.cl new file mode 100644 index 0000000000000..eaa4ac779cfd1 --- /dev/null +++ b/libclc/opencl/lib/generic/integer/bitfield_extract_signed.cl @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifdef cl_khr_extended_bit_ops + +#include +#include + +#define FUNCTION bitfield_extract_signed +#define __RETTYPE __CLC_S_GENTYPE + +#define __CLC_BODY +#include + +#endif // cl_khr_extended_bit_ops diff --git a/libclc/opencl/lib/generic/integer/bitfield_extract_unsigned.cl b/libclc/opencl/lib/generic/integer/bitfield_extract_unsigned.cl new file mode 100644 index 0000000000000..fd63d5d6dee30 --- /dev/null +++ b/libclc/opencl/lib/generic/integer/bitfield_extract_unsigned.cl @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifdef cl_khr_extended_bit_ops + +#include +#include + +#define FUNCTION bitfield_extract_unsigned +#define __RETTYPE __CLC_U_GENTYPE + +#define __CLC_BODY +#include + +#endif // cl_khr_extended_bit_ops diff --git a/libclc/opencl/lib/generic/integer/bitfield_insert.cl b/libclc/opencl/lib/generic/integer/bitfield_insert.cl new file mode 100644 index 0000000000000..6b441155f393b --- /dev/null +++ b/libclc/opencl/lib/generic/integer/bitfield_insert.cl @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifdef cl_khr_extended_bit_ops + +#include +#include + +#define FUNCTION bitfield_insert +#define __CLC_BODY +#include + +#endif // cl_khr_extended_bit_ops diff --git a/libclc/opencl/lib/generic/integer/bitfield_insert.inc b/libclc/opencl/lib/generic/integer/bitfield_insert.inc new file mode 100644 index 0000000000000..b1f45907a4361 --- /dev/null +++ b/libclc/opencl/lib/generic/integer/bitfield_insert.inc @@ -0,0 +1,13 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +_CLC_OVERLOAD _CLC_DEF __CLC_GENTYPE bitfield_insert(__CLC_GENTYPE base, + __CLC_GENTYPE insert, + uint offset, uint count) { + return __clc_bitfield_insert(base, insert, offset, count); +} diff --git a/libclc/opencl/lib/generic/relational/binary_def.inc b/libclc/opencl/lib/generic/relational/binary_def.inc index 54bb237b8f8f5..8416da0475a2c 100644 --- a/libclc/opencl/lib/generic/relational/binary_def.inc +++ b/libclc/opencl/lib/generic/relational/binary_def.inc @@ -10,6 +10,14 @@ #define __IMPL_FUNCTION(x) __CLC_CONCAT(__clc_, x) -_CLC_OVERLOAD _CLC_DEF __CLC_INTN FUNCTION(__CLC_FLOATN a, __CLC_FLOATN b) { +#if __CLC_VECSIZE_OR_1 == 1 +#define __RETTYPE __CLC_INTN +#else +#define __RETTYPE __CLC_BIT_INTN +#endif + +_CLC_OVERLOAD _CLC_DEF __RETTYPE FUNCTION(__CLC_GENTYPE a, __CLC_GENTYPE b) { return __IMPL_FUNCTION(FUNCTION)(a, b); } + +#undef __RETTYPE diff --git a/libclc/opencl/lib/generic/relational/isequal.cl b/libclc/opencl/lib/generic/relational/isequal.cl index 94f83f9452666..83002c28ceab3 100644 --- a/libclc/opencl/lib/generic/relational/isequal.cl +++ b/libclc/opencl/lib/generic/relational/isequal.cl @@ -12,4 +12,4 @@ #define FUNCTION isequal #define __CLC_BODY "binary_def.inc" -#include +#include diff --git a/libclc/opencl/lib/generic/relational/isfinite.cl b/libclc/opencl/lib/generic/relational/isfinite.cl index 695ffea806d5c..a2017133cead8 100644 --- a/libclc/opencl/lib/generic/relational/isfinite.cl +++ b/libclc/opencl/lib/generic/relational/isfinite.cl @@ -12,4 +12,4 @@ #define FUNCTION isfinite #define __CLC_BODY "unary_def.inc" -#include +#include diff --git a/libclc/opencl/lib/generic/relational/isgreater.cl b/libclc/opencl/lib/generic/relational/isgreater.cl index fb46ff20ac608..6eeb2b21c0493 100644 --- a/libclc/opencl/lib/generic/relational/isgreater.cl +++ b/libclc/opencl/lib/generic/relational/isgreater.cl @@ -12,4 +12,4 @@ #define FUNCTION isgreater #define __CLC_BODY "binary_def.inc" -#include +#include diff --git a/libclc/opencl/lib/generic/relational/isgreaterequal.cl b/libclc/opencl/lib/generic/relational/isgreaterequal.cl index b8edde2a05b77..e4e4535fd30d3 100644 --- a/libclc/opencl/lib/generic/relational/isgreaterequal.cl +++ b/libclc/opencl/lib/generic/relational/isgreaterequal.cl @@ -12,4 +12,4 @@ #define FUNCTION isgreaterequal #define __CLC_BODY "binary_def.inc" -#include +#include diff --git a/libclc/opencl/lib/generic/relational/isinf.cl b/libclc/opencl/lib/generic/relational/isinf.cl index 2c15f1f826762..2ab8c182e02a6 100644 --- a/libclc/opencl/lib/generic/relational/isinf.cl +++ b/libclc/opencl/lib/generic/relational/isinf.cl @@ -12,4 +12,4 @@ #define FUNCTION isinf #define __CLC_BODY "unary_def.inc" -#include +#include diff --git a/libclc/opencl/lib/generic/relational/isless.cl b/libclc/opencl/lib/generic/relational/isless.cl index 0af1f53e71042..4212970e7671a 100644 --- a/libclc/opencl/lib/generic/relational/isless.cl +++ b/libclc/opencl/lib/generic/relational/isless.cl @@ -12,4 +12,4 @@ #define FUNCTION isless #define __CLC_BODY "binary_def.inc" -#include +#include diff --git a/libclc/opencl/lib/generic/relational/islessequal.cl b/libclc/opencl/lib/generic/relational/islessequal.cl index 9e32afc718ab2..e7aec262fc762 100644 --- a/libclc/opencl/lib/generic/relational/islessequal.cl +++ b/libclc/opencl/lib/generic/relational/islessequal.cl @@ -12,4 +12,4 @@ #define FUNCTION islessequal #define __CLC_BODY "binary_def.inc" -#include +#include diff --git a/libclc/opencl/lib/generic/relational/islessgreater.cl b/libclc/opencl/lib/generic/relational/islessgreater.cl index c36a857dc3dfc..b775d2484550c 100644 --- a/libclc/opencl/lib/generic/relational/islessgreater.cl +++ b/libclc/opencl/lib/generic/relational/islessgreater.cl @@ -12,4 +12,4 @@ #define FUNCTION islessgreater #define __CLC_BODY "binary_def.inc" -#include +#include diff --git a/libclc/opencl/lib/generic/relational/isnan.cl b/libclc/opencl/lib/generic/relational/isnan.cl index 8b03930c5312f..4b7eeb5b919b6 100644 --- a/libclc/opencl/lib/generic/relational/isnan.cl +++ b/libclc/opencl/lib/generic/relational/isnan.cl @@ -12,4 +12,4 @@ #define FUNCTION isnan #define __CLC_BODY "unary_def.inc" -#include +#include diff --git a/libclc/opencl/lib/generic/relational/isnormal.cl b/libclc/opencl/lib/generic/relational/isnormal.cl index 4ba21cc3e17fc..60ce9dccaeaf3 100644 --- a/libclc/opencl/lib/generic/relational/isnormal.cl +++ b/libclc/opencl/lib/generic/relational/isnormal.cl @@ -12,4 +12,4 @@ #define FUNCTION isnormal #define __CLC_BODY "unary_def.inc" -#include +#include diff --git a/libclc/opencl/lib/generic/relational/isnotequal.cl b/libclc/opencl/lib/generic/relational/isnotequal.cl index 928923b9b2a5e..abb4d3a859663 100644 --- a/libclc/opencl/lib/generic/relational/isnotequal.cl +++ b/libclc/opencl/lib/generic/relational/isnotequal.cl @@ -12,4 +12,4 @@ #define FUNCTION isnotequal #define __CLC_BODY "binary_def.inc" -#include +#include diff --git a/libclc/opencl/lib/generic/relational/isordered.cl b/libclc/opencl/lib/generic/relational/isordered.cl index 60ca4d67ff1ea..684ee425e1203 100644 --- a/libclc/opencl/lib/generic/relational/isordered.cl +++ b/libclc/opencl/lib/generic/relational/isordered.cl @@ -12,4 +12,4 @@ #define FUNCTION isordered #define __CLC_BODY "binary_def.inc" -#include +#include diff --git a/libclc/opencl/lib/generic/relational/isunordered.cl b/libclc/opencl/lib/generic/relational/isunordered.cl index 3392d77856ced..84aa8cafb111a 100644 --- a/libclc/opencl/lib/generic/relational/isunordered.cl +++ b/libclc/opencl/lib/generic/relational/isunordered.cl @@ -12,4 +12,4 @@ #define FUNCTION isunordered #define __CLC_BODY "binary_def.inc" -#include +#include diff --git a/libclc/opencl/lib/generic/relational/signbit.cl b/libclc/opencl/lib/generic/relational/signbit.cl index 26feb8d43fa25..d30fea7b9f6f5 100644 --- a/libclc/opencl/lib/generic/relational/signbit.cl +++ b/libclc/opencl/lib/generic/relational/signbit.cl @@ -12,4 +12,4 @@ #define FUNCTION signbit #define __CLC_BODY "unary_def.inc" -#include +#include diff --git a/libclc/opencl/lib/generic/relational/unary_def.inc b/libclc/opencl/lib/generic/relational/unary_def.inc index 47bb33ef2da3d..f184e3cf0be56 100644 --- a/libclc/opencl/lib/generic/relational/unary_def.inc +++ b/libclc/opencl/lib/generic/relational/unary_def.inc @@ -10,6 +10,14 @@ #define __IMPL_FUNCTION(x) __CLC_CONCAT(__clc_, x) -_CLC_OVERLOAD _CLC_DEF __CLC_INTN FUNCTION(__CLC_FLOATN a) { +#if __CLC_VECSIZE_OR_1 == 1 +#define __RETTYPE __CLC_INTN +#else +#define __RETTYPE __CLC_BIT_INTN +#endif + +_CLC_OVERLOAD _CLC_DEF __RETTYPE FUNCTION(__CLC_GENTYPE a) { return __IMPL_FUNCTION(FUNCTION)(a); } + +#undef __RETTYPE diff --git a/libclc/utils/CMakeLists.txt b/libclc/utils/CMakeLists.txt index ea1d9e9c8ef5f..6851ae16bda07 100644 --- a/libclc/utils/CMakeLists.txt +++ b/libclc/utils/CMakeLists.txt @@ -12,8 +12,8 @@ set( LLVM_LINK_COMPONENTS if( LIBCLC_STANDALONE_BUILD ) add_llvm_executable( prepare_builtins prepare-builtins.cpp ) - set( prepare_builtins_exe prepare_builtins ) - set( prepare_builtins_target prepare_builtins ) + set( prepare_builtins_exe prepare_builtins PARENT_SCOPE ) + set( prepare_builtins_target prepare_builtins PARENT_SCOPE ) else() add_llvm_utility( prepare_builtins prepare-builtins.cpp ) setup_host_tool( prepare_builtins PREPARE_BUILTINS prepare_builtins_exe prepare_builtins_target ) diff --git a/libcxx/.clang-format b/libcxx/.clang-format index f372ac9619997..9557b955cd72c 100644 --- a/libcxx/.clang-format +++ b/libcxx/.clang-format @@ -33,6 +33,7 @@ AttributeMacros: [ '_LIBCPP_DEPRECATED_IN_CXX20', '_LIBCPP_DEPRECATED_IN_CXX23', '_LIBCPP_DEPRECATED', + '_LIBCPP_DIAGNOSE_NULLPTR_IF', '_LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION', '_LIBCPP_EXPORTED_FROM_ABI', '_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS', diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst index 9feea5fffc26c..acfcd367de505 100644 --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -1,10 +1,11 @@ -.. include:: ReleaseNotes/21.rst +.. include:: ReleaseNotes/22.rst .. Make sure to reference the non-live release notes in a toctree to avoid Sphinx errors. .. toctree:: :hidden: ReleaseNotes/20 + ReleaseNotes/21 .. The release notes are in versioned files, but we make sure to keep publishing .. them in an unversioned ReleaseNotes.html page for external sites to reference. diff --git a/libcxx/docs/ReleaseNotes/21.rst b/libcxx/docs/ReleaseNotes/21.rst index 6f18b61284f49..d31ca0130cb80 100644 --- a/libcxx/docs/ReleaseNotes/21.rst +++ b/libcxx/docs/ReleaseNotes/21.rst @@ -10,7 +10,7 @@ Written by the `Libc++ Team `_ .. warning:: - These are in-progress notes for the upcoming libc++ 20.0.0 release. + These are in-progress notes for the upcoming libc++ 21.0.0 release. Release notes for previous releases can be found on `the Download Page `_. @@ -18,7 +18,7 @@ Introduction ============ This document contains the release notes for the libc++ C++ Standard Library, -part of the LLVM Compiler Infrastructure, release 20.0.0. Here we describe the +part of the LLVM Compiler Infrastructure, release 21.0.0. Here we describe the status of libc++ in some detail, including major improvements from the previous release and new feature work. For the general LLVM release notes, see `the LLVM documentation `_. All LLVM releases may diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst new file mode 100644 index 0000000000000..15bf46d44b07f --- /dev/null +++ b/libcxx/docs/ReleaseNotes/22.rst @@ -0,0 +1,59 @@ +=========================================== +Libc++ 22.0.0 (In-Progress) Release Notes +=========================================== + +.. contents:: + :local: + :depth: 2 + +Written by the `Libc++ Team `_ + +.. warning:: + + These are in-progress notes for the upcoming libc++ 22.0.0 release. + Release notes for previous releases can be found on + `the Download Page `_. + +Introduction +============ + +This document contains the release notes for the libc++ C++ Standard Library, +part of the LLVM Compiler Infrastructure, release 22.0.0. Here we describe the +status of libc++ in some detail, including major improvements from the previous +release and new feature work. For the general LLVM release notes, see `the LLVM +documentation `_. All LLVM releases may +be downloaded from the `LLVM releases web site `_. + +For more information about libc++, please see the `Libc++ Web Site +`_ or the `LLVM Web Site `_. + +Note that if you are reading this file from a Git checkout or the +main Libc++ web page, this document applies to the *next* release, not +the current one. To see the release notes for a specific release, please +see the `releases page `_. + +What's New in Libc++ 22.0.0? +============================== + +Implemented Papers +------------------ + +- P2321R2: ``zip`` (`Github `__) (The paper is partially implemented. ``zip_transform_view`` is implemented in this release) + +Improvements and New Features +----------------------------- + +Deprecations and Removals +------------------------- + +Potentially breaking changes +---------------------------- + +Announcements About Future Releases +----------------------------------- + +ABI Affecting Changes +--------------------- + +Build System Changes +-------------------- diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv index e5b2dcf8c1a5b..189f8452e0678 100644 --- a/libcxx/docs/Status/Cxx23Issues.csv +++ b/libcxx/docs/Status/Cxx23Issues.csv @@ -170,7 +170,7 @@ "`LWG3687 `__","``expected`` move constructor should move","2022-07 (Virtual)","|Complete|","16","" "`LWG3692 `__","``zip_view::iterator``'s ``operator<=>`` is overconstrained","2022-07 (Virtual)","|Complete|","20","" "`LWG3701 `__","Make ``formatter, charT>`` requirement explicit","2022-07 (Virtual)","|Complete|","15","" -"`LWG3702 `__","Should ``zip_transform_view::iterator`` remove ``operator<``","2022-07 (Virtual)","","","" +"`LWG3702 `__","Should ``zip_transform_view::iterator`` remove ``operator<``","2022-07 (Virtual)","|Complete|","22","" "`LWG3703 `__","Missing requirements for ``expected`` requires ``is_void``","2022-07 (Virtual)","|Complete|","16","" "`LWG3704 `__","LWG 2059 added overloads that might be ill-formed for sets","2022-07 (Virtual)","","","" "`LWG3705 `__","Hashability shouldn't depend on basic_string's allocator","2022-07 (Virtual)","|Complete|","16","" @@ -222,7 +222,7 @@ "`LWG3765 `__","``const_sentinel`` should be constrained","2022-11 (Kona)","","","" "`LWG3766 `__","``view_interface::cbegin`` is underconstrained","2022-11 (Kona)","","","" "`LWG3770 `__","``const_sentinel_t`` is missing","2022-11 (Kona)","","","" -"`LWG3773 `__","``views::zip_transform`` still requires ``F`` to be ``copy_constructible`` when empty pack","2022-11 (Kona)","","","" +"`LWG3773 `__","``views::zip_transform`` still requires ``F`` to be ``copy_constructible`` when empty pack","2022-11 (Kona)","|Complete|","22","" "`LWG3774 `__","```` should include ````","2022-11 (Kona)","","","" "`LWG3775 `__","Broken dependencies in the ``Cpp17Allocator`` requirements","2022-11 (Kona)","","","" "`LWG3778 `__","``vector`` missing exception specifications","2022-11 (Kona)","|Complete|","3.7","" @@ -234,7 +234,7 @@ "`LWG3792 `__","``__cpp_lib_constexpr_algorithms`` should also be defined in ````","2022-11 (Kona)","|Complete|","16","" "`LWG3795 `__","Self-move-assignment of ``std::future`` and ``std::shared_future`` have unimplementable postconditions","2022-11 (Kona)","","","" "`LWG3796 `__","``movable-box`` as member should use ``default-initialization`` instead of ``copy-initialization``","2022-11 (Kona)","","","" -"`LWG3798 `__","Rvalue reference and ``iterator_category``","2022-11 (Kona)","|Partial|","","``join_with_view``, ``zip_transform_view``, and ``adjacent_transform_view`` haven't been done yet since these types aren't implemented yet" +"`LWG3798 `__","Rvalue reference and ``iterator_category``","2022-11 (Kona)","|Partial|","","``adjacent_transform_view`` hasn't been done yet since this type isn't implemented yet" "`LWG3801 `__","``cartesian_product_view::iterator::distance-from`` ignores the size of last underlying range","2022-11 (Kona)","","","" "`LWG3814 `__","Add freestanding items requested by NB comments","2022-11 (Kona)","","","" "`LWG3816 `__","``flat_map`` and ``flat_multimap`` should impose sequence container requirements","2022-11 (Kona)","","","" diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 4f2a8dddad92c..cd6583cb62c24 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -403,6 +403,7 @@ set(files __format/indic_conjunct_break_table.h __format/parser_std_format_spec.h __format/range_default_formatter.h + __format/range_format.h __format/range_formatter.h __format/unicode.h __format/width_estimation_table.h @@ -514,7 +515,6 @@ set(files __locale_dir/check_grouping.h __locale_dir/get_c_locale.h __locale_dir/locale_base_api.h - __locale_dir/locale_base_api/android.h __locale_dir/locale_base_api/bsd_locale_fallbacks.h __locale_dir/locale_base_api/ibm.h __locale_dir/locale_base_api/musl.h @@ -737,6 +737,7 @@ set(files __ranges/transform_view.h __ranges/view_interface.h __ranges/views.h + __ranges/zip_transform_view.h __ranges/zip_view.h __split_buffer __std_mbstate_t.h @@ -780,7 +781,6 @@ set(files __tuple/make_tuple_types.h __tuple/sfinae_helpers.h __tuple/tuple_element.h - __tuple/tuple_indices.h __tuple/tuple_like.h __tuple/tuple_like_ext.h __tuple/tuple_like_no_subrange.h diff --git a/libcxx/include/__config b/libcxx/include/__config index 1d547eac30952..19398dd276a17 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -265,13 +265,6 @@ _LIBCPP_HARDENING_MODE_DEBUG // When this option is used, the token passed to `std::random_device`'s // constructor *must* be "/dev/urandom" -- anything else is an error. // -// _LIBCPP_USING_NACL_RANDOM -// NaCl's sandbox (which PNaCl also runs in) doesn't allow filesystem access, -// including accesses to the special files under `/dev`. This implementation -// uses the NaCL syscall `nacl_secure_random_init()` to get entropy. -// When this option is used, the token passed to `std::random_device`'s -// constructor *must* be "/dev/urandom" -- anything else is an error. -// // _LIBCPP_USING_WIN32_RANDOM // Use rand_s(), for use on Windows. // When this option is used, the token passed to `std::random_device`'s @@ -283,8 +276,6 @@ _LIBCPP_HARDENING_MODE_DEBUG # define _LIBCPP_USING_GETENTROPY # elif defined(__Fuchsia__) # define _LIBCPP_USING_FUCHSIA_CPRNG -# elif defined(__native_client__) -# define _LIBCPP_USING_NACL_RANDOM # elif defined(_LIBCPP_WIN32API) # define _LIBCPP_USING_WIN32_RANDOM # else @@ -416,6 +407,12 @@ typedef __char32_t char32_t; # define _LIBCPP_GCC_DIAGNOSTIC_IGNORED(str) # endif +// Macros to enter and leave a state where deprecation warnings are suppressed. +# define _LIBCPP_SUPPRESS_DEPRECATED_PUSH \ + _LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wdeprecated") \ + _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wdeprecated-declarations") +# define _LIBCPP_SUPPRESS_DEPRECATED_POP _LIBCPP_DIAGNOSTIC_POP + # if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_FAST # define _LIBCPP_HARDENING_SIG f # elif _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_EXTENSIVE @@ -713,17 +710,6 @@ typedef __char32_t char32_t; # define _LIBCPP_DEPRECATED_WITH_CHAR8_T # endif -// Macros to enter and leave a state where deprecation warnings are suppressed. -# if defined(_LIBCPP_COMPILER_CLANG_BASED) || defined(_LIBCPP_COMPILER_GCC) -# define _LIBCPP_SUPPRESS_DEPRECATED_PUSH \ - _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wdeprecated\"") \ - _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -# define _LIBCPP_SUPPRESS_DEPRECATED_POP _Pragma("GCC diagnostic pop") -# else -# define _LIBCPP_SUPPRESS_DEPRECATED_PUSH -# define _LIBCPP_SUPPRESS_DEPRECATED_POP -# endif - # if _LIBCPP_STD_VER <= 11 # define _LIBCPP_EXPLICIT_SINCE_CXX14 # else @@ -1095,6 +1081,20 @@ typedef __char32_t char32_t; # define _LIBCPP_DIAGNOSE_WARNING(...) # endif +# if __has_attribute(__diagnose_if__) && !defined(_LIBCPP_APPLE_CLANG_VER) && \ + (!defined(_LIBCPP_CLANG_VER) || _LIBCPP_CLANG_VER >= 2001) +# define _LIBCPP_DIAGNOSE_IF(...) __attribute__((__diagnose_if__(__VA_ARGS__))) +# else +# define _LIBCPP_DIAGNOSE_IF(...) +# endif + +# define _LIBCPP_DIAGNOSE_NULLPTR_IF(condition, condition_description) \ + _LIBCPP_DIAGNOSE_IF( \ + condition, \ + "null passed to callee that requires a non-null argument" condition_description, \ + "warning", \ + "nonnull") + # if __has_cpp_attribute(_Clang::__lifetimebound__) # define _LIBCPP_LIFETIMEBOUND [[_Clang::__lifetimebound__]] # else diff --git a/libcxx/include/__config_site.in b/libcxx/include/__config_site.in index fc01aaf2d8746..b68c0c8258366 100644 --- a/libcxx/include/__config_site.in +++ b/libcxx/include/__config_site.in @@ -30,7 +30,6 @@ #cmakedefine01 _LIBCPP_HAS_LOCALIZATION #cmakedefine01 _LIBCPP_HAS_UNICODE #cmakedefine01 _LIBCPP_HAS_WIDE_CHARACTERS -#cmakedefine _LIBCPP_HAS_NO_STD_MODULES #cmakedefine01 _LIBCPP_HAS_TIME_ZONE_DATABASE #cmakedefine01 _LIBCPP_INSTRUMENTED_WITH_ASAN diff --git a/libcxx/include/__flat_map/flat_multimap.h b/libcxx/include/__flat_map/flat_multimap.h index 0af6aac00c383..260d93ed25785 100644 --- a/libcxx/include/__flat_map/flat_multimap.h +++ b/libcxx/include/__flat_map/flat_multimap.h @@ -114,11 +114,12 @@ class flat_multimap { class value_compare { private: _LIBCPP_NO_UNIQUE_ADDRESS key_compare __comp_; - _LIBCPP_HIDE_FROM_ABI value_compare(key_compare __c) : __comp_(__c) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare(key_compare __c) : __comp_(__c) {} friend flat_multimap; public: - _LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator()(const_reference __x, const_reference __y) const { return __comp_(__x.first, __y.first); } }; @@ -137,17 +138,17 @@ class flat_multimap { public: // [flat.map.cons], construct/copy/destroy - _LIBCPP_HIDE_FROM_ABI flat_multimap() noexcept( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap() noexcept( is_nothrow_default_constructible_v<_KeyContainer> && is_nothrow_default_constructible_v<_MappedContainer> && is_nothrow_default_constructible_v<_Compare>) : __containers_(), __compare_() {} - _LIBCPP_HIDE_FROM_ABI flat_multimap(const flat_multimap&) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap(const flat_multimap&) = default; // The copy/move constructors are not specified in the spec, which means they should be defaulted. // However, the move constructor can potentially leave a moved-from object in an inconsistent // state if an exception is thrown. - _LIBCPP_HIDE_FROM_ABI flat_multimap(flat_multimap&& __other) noexcept( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap(flat_multimap&& __other) noexcept( is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_MappedContainer> && is_nothrow_move_constructible_v<_Compare>) # if _LIBCPP_HAS_EXCEPTIONS @@ -168,7 +169,8 @@ class flat_multimap { template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_multimap(const flat_multimap& __other, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multimap(const flat_multimap& __other, const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __other.__containers_.keys, @@ -177,7 +179,7 @@ class flat_multimap { template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_multimap(flat_multimap&& __other, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap(flat_multimap&& __other, const _Allocator& __alloc) # if _LIBCPP_HAS_EXCEPTIONS try # endif // _LIBCPP_HAS_EXCEPTIONS @@ -194,7 +196,7 @@ class flat_multimap { # endif // _LIBCPP_HAS_EXCEPTIONS } - _LIBCPP_HIDE_FROM_ABI flat_multimap( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap( key_container_type __key_cont, mapped_container_type __mapped_cont, const key_compare& __comp = key_compare()) : __containers_{.keys = std::move(__key_cont), .values = std::move(__mapped_cont)}, __compare_(__comp) { _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(), @@ -204,7 +206,7 @@ class flat_multimap { template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_multimap( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap( const key_container_type& __key_cont, const mapped_container_type& __mapped_cont, const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont) { _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(), @@ -214,22 +216,22 @@ class flat_multimap { template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI - flat_multimap(const key_container_type& __key_cont, - const mapped_container_type& __mapped_cont, - const key_compare& __comp, - const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap( + const key_container_type& __key_cont, + const mapped_container_type& __mapped_cont, + const key_compare& __comp, + const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont, __comp) { _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(), "flat_multimap keys and mapped containers have different size"); __sort(); } - _LIBCPP_HIDE_FROM_ABI - flat_multimap(sorted_equivalent_t, - key_container_type __key_cont, - mapped_container_type __mapped_cont, - const key_compare& __comp = key_compare()) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap( + sorted_equivalent_t, + key_container_type __key_cont, + mapped_container_type __mapped_cont, + const key_compare& __comp = key_compare()) : __containers_{.keys = std::move(__key_cont), .values = std::move(__mapped_cont)}, __compare_(__comp) { _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(), "flat_multimap keys and mapped containers have different size"); @@ -238,11 +240,11 @@ class flat_multimap { template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI - flat_multimap(sorted_equivalent_t, - const key_container_type& __key_cont, - const mapped_container_type& __mapped_cont, - const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap( + sorted_equivalent_t, + const key_container_type& __key_cont, + const mapped_container_type& __mapped_cont, + const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont) { _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(), "flat_multimap keys and mapped containers have different size"); @@ -251,33 +253,35 @@ class flat_multimap { template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI - flat_multimap(sorted_equivalent_t, - const key_container_type& __key_cont, - const mapped_container_type& __mapped_cont, - const key_compare& __comp, - const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap( + sorted_equivalent_t, + const key_container_type& __key_cont, + const mapped_container_type& __mapped_cont, + const key_compare& __comp, + const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont, __comp) { _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(), "flat_multimap keys and mapped containers have different size"); _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__is_sorted(__containers_.keys), "Key container is not sorted"); } - _LIBCPP_HIDE_FROM_ABI explicit flat_multimap(const key_compare& __comp) : __containers_(), __compare_(__comp) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit flat_multimap(const key_compare& __comp) + : __containers_(), __compare_(__comp) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_multimap(const key_compare& __comp, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multimap(const key_compare& __comp, const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI explicit flat_multimap(const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit flat_multimap(const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc) {} template requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap(_InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare()) : __containers_(), __compare_(__comp) { insert(__first, __last); @@ -285,7 +289,7 @@ class flat_multimap { template requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>) - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap(_InputIterator __first, _InputIterator __last, const key_compare& __comp, const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) { insert(__first, __last); @@ -293,91 +297,99 @@ class flat_multimap { template requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>) - _LIBCPP_HIDE_FROM_ABI flat_multimap(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multimap(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc) { insert(__first, __last); } template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI flat_multimap(from_range_t __fr, _Range&& __rg) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap(from_range_t __fr, _Range&& __rg) : flat_multimap(__fr, std::forward<_Range>(__rg), key_compare()) {} template <_ContainerCompatibleRange _Range, class _Allocator> requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_multimap(from_range_t, _Range&& __rg, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multimap(from_range_t, _Range&& __rg, const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc) { insert_range(std::forward<_Range>(__rg)); } template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI flat_multimap(from_range_t, _Range&& __rg, const key_compare& __comp) : flat_multimap(__comp) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multimap(from_range_t, _Range&& __rg, const key_compare& __comp) + : flat_multimap(__comp) { insert_range(std::forward<_Range>(__rg)); } template <_ContainerCompatibleRange _Range, class _Allocator> requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_multimap(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multimap(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) { insert_range(std::forward<_Range>(__rg)); } template requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI flat_multimap( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap( sorted_equivalent_t, _InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare()) : __containers_(), __compare_(__comp) { insert(sorted_equivalent, __first, __last); } template requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>) - _LIBCPP_HIDE_FROM_ABI - flat_multimap(sorted_equivalent_t, - _InputIterator __first, - _InputIterator __last, - const key_compare& __comp, - const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap( + sorted_equivalent_t, + _InputIterator __first, + _InputIterator __last, + const key_compare& __comp, + const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) { insert(sorted_equivalent, __first, __last); } template requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>) - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap(sorted_equivalent_t, _InputIterator __first, _InputIterator __last, const _Allocator& __alloc) : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc) { insert(sorted_equivalent, __first, __last); } - _LIBCPP_HIDE_FROM_ABI flat_multimap(initializer_list __il, const key_compare& __comp = key_compare()) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multimap(initializer_list __il, const key_compare& __comp = key_compare()) : flat_multimap(__il.begin(), __il.end(), __comp) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap(initializer_list __il, const key_compare& __comp, const _Allocator& __alloc) : flat_multimap(__il.begin(), __il.end(), __comp, __alloc) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_multimap(initializer_list __il, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multimap(initializer_list __il, const _Allocator& __alloc) : flat_multimap(__il.begin(), __il.end(), __alloc) {} - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap(sorted_equivalent_t, initializer_list __il, const key_compare& __comp = key_compare()) : flat_multimap(sorted_equivalent, __il.begin(), __il.end(), __comp) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_multimap( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap( sorted_equivalent_t, initializer_list __il, const key_compare& __comp, const _Allocator& __alloc) : flat_multimap(sorted_equivalent, __il.begin(), __il.end(), __comp, __alloc) {} template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_multimap(sorted_equivalent_t, initializer_list __il, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multimap(sorted_equivalent_t, initializer_list __il, const _Allocator& __alloc) : flat_multimap(sorted_equivalent, __il.begin(), __il.end(), __alloc) {} - _LIBCPP_HIDE_FROM_ABI flat_multimap& operator=(initializer_list __il) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap& operator=(initializer_list __il) { clear(); insert(__il); return *this; @@ -386,9 +398,9 @@ class flat_multimap { // copy/move assignment are not specified in the spec (defaulted) // but move assignment can potentially leave moved from object in an inconsistent // state if an exception is thrown - _LIBCPP_HIDE_FROM_ABI flat_multimap& operator=(const flat_multimap&) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap& operator=(const flat_multimap&) = default; - _LIBCPP_HIDE_FROM_ABI flat_multimap& operator=(flat_multimap&& __other) noexcept( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap& operator=(flat_multimap&& __other) noexcept( is_nothrow_move_assignable_v<_KeyContainer> && is_nothrow_move_assignable_v<_MappedContainer> && is_nothrow_move_assignable_v<_Compare>) { auto __clear_other_guard = std::__make_scope_guard([&]() noexcept { __other.clear() /* noexcept */; }); @@ -400,38 +412,54 @@ class flat_multimap { } // iterators - _LIBCPP_HIDE_FROM_ABI iterator begin() noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator begin() noexcept { return iterator(__containers_.keys.begin(), __containers_.values.begin()); } - _LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator begin() const noexcept { return const_iterator(__containers_.keys.begin(), __containers_.values.begin()); } - _LIBCPP_HIDE_FROM_ABI iterator end() noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator end() noexcept { return iterator(__containers_.keys.end(), __containers_.values.end()); } - _LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator end() const noexcept { return const_iterator(__containers_.keys.end(), __containers_.values.end()); } - _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() noexcept { return reverse_iterator(begin()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rbegin() noexcept { + return reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rbegin() const noexcept { + return const_reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rend() noexcept { + return reverse_iterator(begin()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rend() const noexcept { + return const_reverse_iterator(begin()); + } - _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return begin(); } - _LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return end(); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cbegin() const noexcept { return begin(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cend() const noexcept { return end(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crbegin() const noexcept { + return const_reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crend() const noexcept { + return const_reverse_iterator(begin()); + } // [flat.map.capacity], capacity - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __containers_.keys.empty(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool empty() const noexcept { + return __containers_.keys.empty(); + } - _LIBCPP_HIDE_FROM_ABI size_type size() const noexcept { return __containers_.keys.size(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type size() const noexcept { + return __containers_.keys.size(); + } - _LIBCPP_HIDE_FROM_ABI size_type max_size() const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type max_size() const noexcept { return std::min(__containers_.keys.max_size(), __containers_.values.max_size()); } @@ -439,7 +467,7 @@ class flat_multimap { template requires is_constructible_v, _Args...> && is_move_constructible_v && is_move_constructible_v - _LIBCPP_HIDE_FROM_ABI iterator emplace(_Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator emplace(_Args&&... __args) { std::pair __pair(std::forward<_Args>(__args)...); auto __key_it = std::upper_bound(__containers_.keys.begin(), __containers_.keys.end(), __pair.first, __compare_); auto __mapped_it = __corresponding_mapped_it(*this, __key_it); @@ -450,7 +478,7 @@ class flat_multimap { template requires is_constructible_v, _Args...> - _LIBCPP_HIDE_FROM_ABI iterator emplace_hint(const_iterator __hint, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator emplace_hint(const_iterator __hint, _Args&&... __args) { std::pair __pair(std::forward<_Args>(__args)...); auto __prev_larger = __hint != cbegin() && __compare_(__pair.first, (__hint - 1)->first); @@ -490,33 +518,35 @@ class flat_multimap { *this, __key_iter, __mapped_iter, std::move(__pair.first), std::move(__pair.second)); } - _LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __x) { return emplace(__x); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const value_type& __x) { return emplace(__x); } - _LIBCPP_HIDE_FROM_ABI iterator insert(value_type&& __x) { return emplace(std::move(__x)); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(value_type&& __x) { + return emplace(std::move(__x)); + } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, const value_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, const value_type& __x) { return emplace_hint(__hint, __x); } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, value_type&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, value_type&& __x) { return emplace_hint(__hint, std::move(__x)); } template requires is_constructible_v, _PairLike> - _LIBCPP_HIDE_FROM_ABI iterator insert(_PairLike&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(_PairLike&& __x) { return emplace(std::forward<_PairLike>(__x)); } template requires is_constructible_v, _PairLike> - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, _PairLike&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, _PairLike&& __x) { return emplace_hint(__hint, std::forward<_PairLike>(__x)); } template requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(_InputIterator __first, _InputIterator __last) { if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) { __reserve(__last - __first); } @@ -525,7 +555,8 @@ class flat_multimap { template requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI void insert(sorted_equivalent_t, _InputIterator __first, _InputIterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + insert(sorted_equivalent_t, _InputIterator __first, _InputIterator __last) { if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) { __reserve(__last - __first); } @@ -534,7 +565,7 @@ class flat_multimap { } template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert_range(_Range&& __range) { if constexpr (ranges::sized_range<_Range>) { __reserve(ranges::size(__range)); } @@ -542,19 +573,23 @@ class flat_multimap { __append_sort_merge(ranges::begin(__range), ranges::end(__range)); } - _LIBCPP_HIDE_FROM_ABI void insert(initializer_list __il) { insert(__il.begin(), __il.end()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(initializer_list __il) { + insert(__il.begin(), __il.end()); + } - _LIBCPP_HIDE_FROM_ABI void insert(sorted_equivalent_t, initializer_list __il) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + insert(sorted_equivalent_t, initializer_list __il) { insert(sorted_equivalent, __il.begin(), __il.end()); } - _LIBCPP_HIDE_FROM_ABI containers extract() && { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 containers extract() && { auto __guard = std::__make_scope_guard([&]() noexcept { clear() /* noexcept */; }); auto __ret = std::move(__containers_); return __ret; } - _LIBCPP_HIDE_FROM_ABI void replace(key_container_type&& __key_cont, mapped_container_type&& __mapped_cont) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + replace(key_container_type&& __key_cont, mapped_container_type&& __mapped_cont) { _LIBCPP_ASSERT_VALID_INPUT_RANGE( __key_cont.size() == __mapped_cont.size(), "flat_multimap keys and mapped containers have different size"); @@ -565,15 +600,15 @@ class flat_multimap { __guard.__complete(); } - _LIBCPP_HIDE_FROM_ABI iterator erase(iterator __position) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(iterator __position) { return __erase(__position.__key_iter_, __position.__mapped_iter_); } - _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __position) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __position) { return __erase(__position.__key_iter_, __position.__mapped_iter_); } - _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(const key_type& __x) { auto [__first, __last] = equal_range(__x); auto __res = __last - __first; erase(__first, __last); @@ -583,14 +618,14 @@ class flat_multimap { template requires(__is_compare_transparent && !is_convertible_v<_Kp &&, iterator> && !is_convertible_v<_Kp &&, const_iterator>) - _LIBCPP_HIDE_FROM_ABI size_type erase(_Kp&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(_Kp&& __x) { auto [__first, __last] = equal_range(__x); auto __res = __last - __first; erase(__first, __last); return __res; } - _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __first, const_iterator __last) { auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); auto __key_it = __containers_.keys.erase(__first.__key_iter_, __last.__key_iter_); auto __mapped_it = __containers_.values.erase(__first.__mapped_iter_, __last.__mapped_iter_); @@ -598,7 +633,7 @@ class flat_multimap { return iterator(std::move(__key_it), std::move(__mapped_it)); } - _LIBCPP_HIDE_FROM_ABI void swap(flat_multimap& __y) noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(flat_multimap& __y) noexcept { // warning: The spec has unconditional noexcept, which means that // if any of the following functions throw an exception, // std::terminate will be called @@ -607,137 +642,160 @@ class flat_multimap { ranges::swap(__containers_.values, __y.__containers_.values); } - _LIBCPP_HIDE_FROM_ABI void clear() noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void clear() noexcept { __containers_.keys.clear(); __containers_.values.clear(); } // observers - _LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __compare_; } - _LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return value_compare(__compare_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 key_compare key_comp() const { return __compare_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare value_comp() const { + return value_compare(__compare_); + } - _LIBCPP_HIDE_FROM_ABI const key_container_type& keys() const noexcept { return __containers_.keys; } - _LIBCPP_HIDE_FROM_ABI const mapped_container_type& values() const noexcept { return __containers_.values; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const key_container_type& keys() const noexcept { + return __containers_.keys; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const mapped_container_type& values() const noexcept { + return __containers_.values; + } // map operations - _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __x) { return __find_impl(*this, __x); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const key_type& __x) { + return __find_impl(*this, __x); + } - _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __x) const { return __find_impl(*this, __x); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const key_type& __x) const { + return __find_impl(*this, __x); + } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI iterator find(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const _Kp& __x) { return __find_impl(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI const_iterator find(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const _Kp& __x) const { return __find_impl(*this, __x); } - _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const key_type& __x) const { auto [__first, __last] = equal_range(__x); return __last - __first; } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI size_type count(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const _Kp& __x) const { auto [__first, __last] = equal_range(__x); return __last - __first; } - _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __x) const { return find(__x) != end(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const key_type& __x) const { + return find(__x) != end(); + } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI bool contains(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const _Kp& __x) const { return find(__x) != end(); } - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __x) { return __lower_bound(*this, __x); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const key_type& __x) { + return __lower_bound(*this, __x); + } - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const key_type& __x) const { return __lower_bound(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const _Kp& __x) { return __lower_bound(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const _Kp& __x) const { return __lower_bound(*this, __x); } - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __x) { return __upper_bound(*this, __x); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const key_type& __x) { + return __upper_bound(*this, __x); + } - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const key_type& __x) const { return __upper_bound(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const _Kp& __x) { return __upper_bound(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const _Kp& __x) const { return __upper_bound(*this, __x); } - _LIBCPP_HIDE_FROM_ABI pair equal_range(const key_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair equal_range(const key_type& __x) { return __equal_range_impl(*this, __x); } - _LIBCPP_HIDE_FROM_ABI pair equal_range(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + equal_range(const key_type& __x) const { return __equal_range_impl(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI pair equal_range(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair equal_range(const _Kp& __x) { return __equal_range_impl(*this, __x); } template requires __is_compare_transparent - _LIBCPP_HIDE_FROM_ABI pair equal_range(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + equal_range(const _Kp& __x) const { return __equal_range_impl(*this, __x); } - friend _LIBCPP_HIDE_FROM_ABI bool operator==(const flat_multimap& __x, const flat_multimap& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator==(const flat_multimap& __x, const flat_multimap& __y) { return ranges::equal(__x, __y); } - friend _LIBCPP_HIDE_FROM_ABI auto operator<=>(const flat_multimap& __x, const flat_multimap& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 auto + operator<=>(const flat_multimap& __x, const flat_multimap& __y) { return std::lexicographical_compare_three_way( __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way); } - friend _LIBCPP_HIDE_FROM_ABI void swap(flat_multimap& __x, flat_multimap& __y) noexcept { __x.swap(__y); } + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + swap(flat_multimap& __x, flat_multimap& __y) noexcept { + __x.swap(__y); + } private: struct __ctor_uses_allocator_tag { - explicit _LIBCPP_HIDE_FROM_ABI __ctor_uses_allocator_tag() = default; + explicit _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __ctor_uses_allocator_tag() = default; }; struct __ctor_uses_allocator_empty_tag { - explicit _LIBCPP_HIDE_FROM_ABI __ctor_uses_allocator_empty_tag() = default; + explicit _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __ctor_uses_allocator_empty_tag() = default; }; template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI - flat_multimap(__ctor_uses_allocator_tag, - const _Allocator& __alloc, - _KeyCont&& __key_cont, - _MappedCont&& __mapped_cont, - _CompArg&&... __comp) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multimap( + __ctor_uses_allocator_tag, + const _Allocator& __alloc, + _KeyCont&& __key_cont, + _MappedCont&& __mapped_cont, + _CompArg&&... __comp) : __containers_{.keys = std::make_obj_using_allocator( __alloc, std::forward<_KeyCont>(__key_cont)), .values = std::make_obj_using_allocator( @@ -746,29 +804,32 @@ class flat_multimap { template requires __allocator_ctor_constraint<_Allocator> - _LIBCPP_HIDE_FROM_ABI flat_multimap(__ctor_uses_allocator_empty_tag, const _Allocator& __alloc, _CompArg&&... __comp) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multimap(__ctor_uses_allocator_empty_tag, const _Allocator& __alloc, _CompArg&&... __comp) : __containers_{.keys = std::make_obj_using_allocator(__alloc), .values = std::make_obj_using_allocator(__alloc)}, __compare_(std::forward<_CompArg>(__comp)...) {} - _LIBCPP_HIDE_FROM_ABI bool __is_sorted(auto&& __key_container) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __is_sorted(auto&& __key_container) const { return ranges::is_sorted(__key_container, __compare_); } - _LIBCPP_HIDE_FROM_ABI void __sort() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __sort() { auto __zv = ranges::views::zip(__containers_.keys, __containers_.values); ranges::sort(__zv, __compare_, [](const auto& __p) -> decltype(auto) { return std::get<0>(__p); }); } template - _LIBCPP_HIDE_FROM_ABI static auto __corresponding_mapped_it(_Self&& __self, _KeyIter&& __key_iter) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto + __corresponding_mapped_it(_Self&& __self, _KeyIter&& __key_iter) { return __self.__containers_.values.begin() + static_cast>( ranges::distance(__self.__containers_.keys.begin(), __key_iter)); } template - _LIBCPP_HIDE_FROM_ABI void __append_sort_merge(_InputIterator __first, _Sentinel __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + __append_sort_merge(_InputIterator __first, _Sentinel __last) { auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); size_t __num_appended = __flat_map_utils::__append(*this, std::move(__first), std::move(__last)); if (__num_appended != 0) { @@ -791,7 +852,7 @@ class flat_multimap { } template - _LIBCPP_HIDE_FROM_ABI static auto __find_impl(_Self&& __self, const _Kp& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto __find_impl(_Self&& __self, const _Kp& __key) { auto __it = __self.lower_bound(__key); auto __last = __self.end(); if (__it == __last || __self.__compare_(__key, __it->first)) { @@ -801,7 +862,7 @@ class flat_multimap { } template - _LIBCPP_HIDE_FROM_ABI static auto __equal_range_impl(_Self&& __self, const _Kp& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto __equal_range_impl(_Self&& __self, const _Kp& __key) { auto [__key_first, __key_last] = std::equal_range(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __key, __self.__compare_); @@ -811,7 +872,7 @@ class flat_multimap { } template - _LIBCPP_HIDE_FROM_ABI static _Res __lower_bound(_Self&& __self, _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static _Res __lower_bound(_Self&& __self, _Kp& __x) { auto __key_iter = std::lower_bound(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __x, __self.__compare_); auto __mapped_iter = __corresponding_mapped_it(__self, __key_iter); @@ -819,14 +880,14 @@ class flat_multimap { } template - _LIBCPP_HIDE_FROM_ABI static _Res __upper_bound(_Self&& __self, _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static _Res __upper_bound(_Self&& __self, _Kp& __x) { auto __key_iter = std::upper_bound(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __x, __self.__compare_); auto __mapped_iter = __corresponding_mapped_it(__self, __key_iter); return _Res(std::move(__key_iter), std::move(__mapped_iter)); } - _LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __reserve(size_t __size) { if constexpr (__container_traits<_KeyContainer>::__reservable) { __containers_.keys.reserve(__size); } @@ -837,7 +898,8 @@ class flat_multimap { } template - _LIBCPP_HIDE_FROM_ABI iterator __erase(_KIter __key_iter_to_remove, _MIter __mapped_iter_to_remove) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __erase(_KIter __key_iter_to_remove, _MIter __mapped_iter_to_remove) { auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); auto __key_iter = __containers_.keys.erase(__key_iter_to_remove); auto __mapped_iter = __containers_.values.erase(__mapped_iter_to_remove); @@ -847,7 +909,8 @@ class flat_multimap { template friend typename flat_multimap<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>::size_type - erase_if(flat_multimap<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>&, _Predicate); + _LIBCPP_CONSTEXPR_SINCE_CXX26 + erase_if(flat_multimap<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>&, _Predicate); friend __flat_map_utils; @@ -855,8 +918,9 @@ class flat_multimap { _LIBCPP_NO_UNIQUE_ADDRESS key_compare __compare_; struct __key_equiv { - _LIBCPP_HIDE_FROM_ABI __key_equiv(key_compare __c) : __comp_(__c) {} - _LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_equiv(key_compare __c) : __comp_(__c) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator()(const_reference __x, const_reference __y) const { return !__comp_(std::get<0>(__x), std::get<0>(__y)) && !__comp_(std::get<0>(__y), std::get<0>(__x)); } key_compare __comp_; @@ -980,8 +1044,9 @@ struct uses_allocator && uses_allocator_v<_MappedContainer, _Allocator>> {}; template -_LIBCPP_HIDE_FROM_ABI typename flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>::size_type -erase_if(flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>& __flat_multimap, _Predicate __pred) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + typename flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>::size_type + erase_if(flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>& __flat_multimap, _Predicate __pred) { auto __zv = ranges::views::zip(__flat_multimap.__containers_.keys, __flat_multimap.__containers_.values); auto __first = __zv.begin(); auto __last = __zv.end(); diff --git a/libcxx/include/__format/range_default_formatter.h b/libcxx/include/__format/range_default_formatter.h index 7149debb2f141..2769647ad527e 100644 --- a/libcxx/include/__format/range_default_formatter.h +++ b/libcxx/include/__format/range_default_formatter.h @@ -16,10 +16,10 @@ #include <__algorithm/ranges_copy.h> #include <__chrono/statically_widen.h> -#include <__concepts/same_as.h> #include <__config> #include <__format/concepts.h> #include <__format/formatter.h> +#include <__format/range_format.h> #include <__format/range_formatter.h> #include <__iterator/back_insert_iterator.h> #include <__ranges/concepts.h> @@ -42,51 +42,11 @@ concept __const_formattable_range = template using __fmt_maybe_const _LIBCPP_NODEBUG = conditional_t<__const_formattable_range<_Rp, _CharT>, const _Rp, _Rp>; -_LIBCPP_DIAGNOSTIC_PUSH -_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wshadow") -_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshadow") -// This shadows map, set, and string. -enum class range_format { disabled, map, set, sequence, string, debug_string }; -_LIBCPP_DIAGNOSTIC_POP - // There is no definition of this struct, it's purely intended to be used to // generate diagnostics. template struct __instantiated_the_primary_template_of_format_kind; -template -constexpr range_format format_kind = [] { - // [format.range.fmtkind]/1 - // A program that instantiates the primary template of format_kind is ill-formed. - static_assert(sizeof(_Rp) != sizeof(_Rp), "create a template specialization of format_kind for your type"); - return range_format::disabled; -}(); - -template - requires same_as<_Rp, remove_cvref_t<_Rp>> -inline constexpr range_format format_kind<_Rp> = [] { - // [format.range.fmtkind]/2 - - // 2.1 If same_as>, R> is true, - // Otherwise format_kind is range_format::disabled. - if constexpr (same_as>, _Rp>) - return range_format::disabled; - // 2.2 Otherwise, if the qualified-id R::key_type is valid and denotes a type: - else if constexpr (requires { typename _Rp::key_type; }) { - // 2.2.1 If the qualified-id R::mapped_type is valid and denotes a type ... - if constexpr (requires { typename _Rp::mapped_type; } && - // 2.2.1 ... If either U is a specialization of pair or U is a specialization - // of tuple and tuple_size_v == 2 - __fmt_pair_like>>) - return range_format::map; - else - // 2.2.2 Otherwise format_kind is range_format::set. - return range_format::set; - } else - // 2.3 Otherwise, format_kind is range_format::sequence. - return range_format::sequence; -}(); - template struct __range_default_formatter; diff --git a/libcxx/include/__format/range_format.h b/libcxx/include/__format/range_format.h new file mode 100644 index 0000000000000..139cfd92ee32b --- /dev/null +++ b/libcxx/include/__format/range_format.h @@ -0,0 +1,71 @@ +// -*- 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___FORMAT_RANGE_FORMAT_H +#define _LIBCPP___FORMAT_RANGE_FORMAT_H + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#include <__concepts/same_as.h> +#include <__config> +#include <__format/concepts.h> +#include <__ranges/concepts.h> +#include <__type_traits/remove_cvref.h> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_DIAGNOSTIC_PUSH +_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wshadow") +_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshadow") +// This shadows map, set, and string. +enum class range_format { disabled, map, set, sequence, string, debug_string }; +_LIBCPP_DIAGNOSTIC_POP + +template +constexpr range_format format_kind = [] { + // [format.range.fmtkind]/1 + // A program that instantiates the primary template of format_kind is ill-formed. + static_assert(sizeof(_Rp) != sizeof(_Rp), "create a template specialization of format_kind for your type"); + return range_format::disabled; +}(); + +template + requires same_as<_Rp, remove_cvref_t<_Rp>> +inline constexpr range_format format_kind<_Rp> = [] { + // [format.range.fmtkind]/2 + + // 2.1 If same_as>, R> is true, + // Otherwise format_kind is range_format::disabled. + if constexpr (same_as>, _Rp>) + return range_format::disabled; + // 2.2 Otherwise, if the qualified-id R::key_type is valid and denotes a type: + else if constexpr (requires { typename _Rp::key_type; }) { + // 2.2.1 If the qualified-id R::mapped_type is valid and denotes a type ... + if constexpr (requires { typename _Rp::mapped_type; } && + // 2.2.1 ... If either U is a specialization of pair or U is a specialization + // of tuple and tuple_size_v == 2 + __fmt_pair_like>>) + return range_format::map; + else + // 2.2.2 Otherwise format_kind is range_format::set. + return range_format::set; + } else + // 2.3 Otherwise, format_kind is range_format::sequence. + return range_format::sequence; +}(); + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +#endif diff --git a/libcxx/include/__functional/bind.h b/libcxx/include/__functional/bind.h index 596cce03cdb58..def9e4c4ec7a9 100644 --- a/libcxx/include/__functional/bind.h +++ b/libcxx/include/__functional/bind.h @@ -83,15 +83,14 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& __mu(reference_w template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __invoke_result_t<_Ti&, _Uj...> -__mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __tuple_indices<_Indx...>) { +__mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __index_sequence<_Indx...>) { return __ti(std::forward<_Uj>(std::get<_Indx>(__uj))...); } template ::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __invoke_result_t<_Ti&, _Uj...> __mu(_Ti& __ti, tuple<_Uj...>& __uj) { - typedef typename __make_tuple_indices::type __indices; - return std::__mu_expand(__ti, __uj, __indices()); + return std::__mu_expand(__ti, __uj, __make_index_sequence()); } template @@ -191,7 +190,7 @@ struct __bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj, true> { template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __bind_return<_Fp, _BoundArgs, _Args>::type -__apply_functor(_Fp& __f, _BoundArgs& __bound_args, __tuple_indices<_Indx...>, _Args&& __args) { +__apply_functor(_Fp& __f, _BoundArgs& __bound_args, __index_sequence<_Indx...>, _Args&& __args) { return std::__invoke(__f, std::__mu(std::get<_Indx>(__bound_args), __args)...); } @@ -205,8 +204,6 @@ class __bind : public __weak_result_type<__decay_t<_Fp> > { _Fd __f_; _Td __bound_args_; - typedef typename __make_tuple_indices::type __indices; - public: template < class _Gp, @@ -219,14 +216,22 @@ class __bind : public __weak_result_type<__decay_t<_Fp> > { template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type operator()(_Args&&... __args) { - return std::__apply_functor(__f_, __bound_args_, __indices(), tuple<_Args&&...>(std::forward<_Args>(__args)...)); + return std::__apply_functor( + __f_, + __bound_args_, + __make_index_sequence(), + tuple<_Args&&...>(std::forward<_Args>(__args)...)); } template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __bind_return >::type operator()(_Args&&... __args) const { - return std::__apply_functor(__f_, __bound_args_, __indices(), tuple<_Args&&...>(std::forward<_Args>(__args)...)); + return std::__apply_functor( + __f_, + __bound_args_, + __make_index_sequence(), + tuple<_Args&&...>(std::forward<_Args>(__args)...)); } }; diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index 78f2f3bfd2f4c..03f50d9f3f269 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -122,6 +122,19 @@ struct __get_hash_node_value_type<__hash_value_type<_Key, _Tp> > { template using __get_hash_node_value_type_t _LIBCPP_NODEBUG = typename __get_hash_node_value_type<_Tp>::type; +template +struct __get_hash_node_key_type { + using type _LIBCPP_NODEBUG = _Tp; +}; + +template +struct __get_hash_node_key_type<__hash_value_type<_Key, _Tp> > { + using type _LIBCPP_NODEBUG = _Key; +}; + +template +using __get_hash_node_key_type_t _LIBCPP_NODEBUG = typename __get_hash_node_key_type<_Tp>::type; + template struct __hash_node : public __hash_node_base< __rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > > { using __node_value_type _LIBCPP_NODEBUG = __get_hash_node_value_type_t<_Tp>; @@ -182,69 +195,11 @@ class __hash_map_iterator; template class __hash_map_const_iterator; -template -struct __hash_key_value_types { - static_assert(!is_reference<_Tp>::value && !is_const<_Tp>::value, ""); - typedef _Tp key_type; - typedef _Tp __node_value_type; - typedef _Tp __container_value_type; - static const bool __is_map = false; - - _LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(_Tp const& __v) { return __v; } - _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(__node_value_type const& __v) { return __v; } - _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) { return std::addressof(__n); } - _LIBCPP_HIDE_FROM_ABI static __container_value_type&& __move(__node_value_type& __v) { return std::move(__v); } -}; - -template -struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > { - typedef _Key key_type; - typedef _Tp mapped_type; - typedef __hash_value_type<_Key, _Tp> __node_value_type; - typedef pair __container_value_type; - typedef __container_value_type __map_value_type; - static const bool __is_map = true; - - _LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(__container_value_type const& __v) { return __v.first; } - - template , __node_value_type>::value, int> = 0> - _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(_Up& __t) { - return __t.__get_value(); - } - - template , __container_value_type>::value, int> = 0> - _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(_Up& __t) { - return __t; - } - - _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__container_value_type& __n) { - return std::addressof(__n); - } - _LIBCPP_HIDE_FROM_ABI static pair __move(__node_value_type& __v) { return __v.__move(); } -}; - -template , bool = _KVTypes::__is_map> -struct __hash_map_pointer_types {}; - -template -struct __hash_map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> { - typedef typename _KVTypes::__map_value_type _Mv; - typedef __rebind_pointer_t<_AllocPtr, _Mv> __map_value_type_pointer; - typedef __rebind_pointer_t<_AllocPtr, const _Mv> __const_map_value_type_pointer; -}; - template ::element_type> struct __hash_node_types; template -struct __hash_node_types<_NodePtr, __hash_node<_Tp, _VoidPtr> > - : public __hash_key_value_types<_Tp>, - __hash_map_pointer_types<_Tp, _VoidPtr> - -{ - typedef __hash_key_value_types<_Tp> __base; - -public: +struct __hash_node_types<_NodePtr, __hash_node<_Tp, _VoidPtr> > { typedef ptrdiff_t difference_type; typedef size_t size_type; @@ -617,8 +572,6 @@ public: typedef typename __alloc_traits::pointer pointer; private: - typedef __hash_node_types _NodeTypes; - allocator_type& __na_; public: @@ -633,7 +586,7 @@ public: _LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT { if (__value_constructed) { - __alloc_traits::destroy(__na_, _NodeTypes::__get_ptr(__p->__get_value())); + __alloc_traits::destroy(__na_, std::addressof(__p->__get_value())); std::__destroy_at(std::addressof(*__p)); } if (__p) @@ -684,6 +637,8 @@ template class __hash_table { public: using value_type = __get_hash_node_value_type_t<_Tp>; + using key_type = __get_hash_node_key_type_t<_Tp>; + typedef _Hash hasher; typedef _Equal key_equal; typedef _Alloc allocator_type; @@ -694,8 +649,6 @@ private: public: typedef typename _NodeTypes::__node_value_type __node_value_type; - typedef typename _NodeTypes::__container_value_type __container_value_type; - typedef typename _NodeTypes::key_type key_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename __alloc_traits::pointer pointer; @@ -824,7 +777,7 @@ public: template ::value, int> = 0> + __enable_if_t<__can_extract_map_key<_First, key_type, value_type>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI pair __emplace_unique(_First&& __f, _Second&& __s) { return __emplace_unique_key_args(__f, std::forward<_First>(__f), std::forward<_Second>(__s)); } @@ -854,9 +807,7 @@ public: template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI void __insert_unique_from_orphaned_node(value_type&& __value) { - using __key_type = typename _NodeTypes::key_type; - - __node_holder __h = __construct_node(const_cast<__key_type&&>(__value.first), std::move(__value.second)); + __node_holder __h = __construct_node(const_cast(__value.first), std::move(__value.second)); __node_insert_unique(__h.get()); __h.release(); } @@ -870,9 +821,7 @@ public: template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI void __insert_multi_from_orphaned_node(value_type&& __value) { - using __key_type = typename _NodeTypes::key_type; - - __node_holder __h = __construct_node(const_cast<__key_type&&>(__value.first), std::move(__value.second)); + __node_holder __h = __construct_node(const_cast(__value.first), std::move(__value.second)); __node_insert_multi(__h.get()); __h.release(); } @@ -1047,12 +996,10 @@ private: template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI void __assign_value(__get_hash_node_value_type_t<_Tp>& __lhs, _From&& __rhs) { - using __key_type = typename _NodeTypes::key_type; - // This is technically UB, since the object was constructed as `const`. // Clang doesn't optimize on this currently though. - const_cast<__key_type&>(__lhs.first) = const_cast<__copy_cvref_t<_From, __key_type>&&>(__rhs.first); - __lhs.second = std::forward<_From>(__rhs).second; + const_cast(__lhs.first) = const_cast<__copy_cvref_t<_From, key_type>&&>(__rhs.first); + __lhs.second = std::forward<_From>(__rhs).second; } template ::value, int> = 0> @@ -1201,7 +1148,7 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate_node(__next_pointer while (__np != nullptr) { __next_pointer __next = __np->__next_; __node_pointer __real_np = __np->__upcast(); - __node_traits::destroy(__na, _NodeTypes::__get_ptr(__real_np->__get_value())); + __node_traits::destroy(__na, std::addressof(__real_np->__get_value())); std::__destroy_at(std::addressof(*__real_np)); __node_traits::deallocate(__na, __real_np, 1); __np = __next; @@ -1290,8 +1237,8 @@ template void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first, _InputIterator __last) { typedef iterator_traits<_InputIterator> _ITraits; typedef typename _ITraits::value_type _ItValueType; - static_assert(is_same<_ItValueType, __container_value_type>::value, - "__assign_unique may only be called with the containers value type"); + static_assert( + is_same<_ItValueType, value_type>::value, "__assign_unique may only be called with the containers value type"); if (bucket_count() != 0) { __next_pointer __cache = __detach(); @@ -1321,10 +1268,8 @@ template void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first, _InputIterator __last) { typedef iterator_traits<_InputIterator> _ITraits; typedef typename _ITraits::value_type _ItValueType; - static_assert( - (is_same<_ItValueType, __container_value_type>::value || is_same<_ItValueType, __node_value_type>::value), - "__assign_multi may only be called with the containers value type" - " or the nodes value type"); + static_assert(is_same<_ItValueType, value_type>::value, + "__assign_multi may only be called with the containers value type or the nodes value type"); if (bucket_count() != 0) { __next_pointer __cache = __detach(); #if _LIBCPP_HAS_EXCEPTIONS @@ -1345,7 +1290,7 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __f __deallocate_node(__cache); } for (; __first != __last; ++__first) - __emplace_multi(_NodeTypes::__get_value(*__first)); + __emplace_multi(*__first); } template @@ -1863,7 +1808,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&&... __args) { std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ 0); // Now construct the value_type using the allocator's construct() method. - __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__get_value()), std::forward<_Args>(__args)...); + __node_traits::construct(__na, std::addressof(__h->__get_value()), std::forward<_Args>(__args)...); __h.get_deleter().__value_constructed = true; __h->__hash_ = hash_function()(__h->__get_value()); @@ -1879,7 +1824,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(size_t __hash, _ __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ __hash); __node_traits::construct( - __na, _NodeTypes::__get_ptr(__h->__get_value()), std::forward<_First>(__f), std::forward<_Rest>(__rest)...); + __na, std::addressof(__h->__get_value()), std::forward<_First>(__f), std::forward<_Rest>(__rest)...); __h.get_deleter().__value_constructed = true; return __h; } diff --git a/libcxx/include/__locale_dir/locale_base_api.h b/libcxx/include/__locale_dir/locale_base_api.h index 8dbc28e839839..9f3ce02a3af20 100644 --- a/libcxx/include/__locale_dir/locale_base_api.h +++ b/libcxx/include/__locale_dir/locale_base_api.h @@ -129,8 +129,6 @@ // will define those directly. # if defined(_AIX) || defined(__MVS__) # include <__locale_dir/locale_base_api/ibm.h> -# elif defined(__ANDROID__) -# include <__locale_dir/locale_base_api/android.h> # elif defined(__OpenBSD__) # include <__locale_dir/locale_base_api/openbsd.h> # elif defined(__wasi__) || _LIBCPP_HAS_MUSL_LIBC diff --git a/libcxx/include/__locale_dir/locale_base_api/android.h b/libcxx/include/__locale_dir/locale_base_api/android.h deleted file mode 100644 index 36b8d93e1b228..0000000000000 --- a/libcxx/include/__locale_dir/locale_base_api/android.h +++ /dev/null @@ -1,45 +0,0 @@ -// -*- 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___LOCALE_DIR_LOCALE_BASE_API_ANDROID_H -#define _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_ANDROID_H - -#include - -// FIXME: Is this actually required? -extern "C" { -#include -} - -#include - -// If we do not have this header, we are in a platform build rather than an NDK -// build, which will always be at least as new as the ToT NDK, in which case we -// don't need any of the inlines below since libc provides them. -#if __has_include() -# include -// In NDK versions later than 16, locale-aware functions are provided by -// legacy_stdlib_inlines.h -# if __NDK_MAJOR__ <= 16 -# if __ANDROID_API__ < 26 - -inline _LIBCPP_HIDE_FROM_ABI float strtof_l(const char* __nptr, char** __endptr, locale_t) { - return ::strtof(__nptr, __endptr); -} - -inline _LIBCPP_HIDE_FROM_ABI double strtod_l(const char* __nptr, char** __endptr, locale_t) { - return ::strtod(__nptr, __endptr); -} - -# endif // __ANDROID_API__ < 26 - -# endif // __NDK_MAJOR__ <= 16 -#endif // __has_include() - -#endif // _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_ANDROID_H diff --git a/libcxx/include/__memory/construct_at.h b/libcxx/include/__memory/construct_at.h index b64e64b5a29b0..658269158d945 100644 --- a/libcxx/include/__memory/construct_at.h +++ b/libcxx/include/__memory/construct_at.h @@ -33,7 +33,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template ()) _Tp(std::declval<_Args>()...))> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp* construct_at(_Tp* __location, _Args&&... __args) { +_LIBCPP_HIDE_FROM_ABI constexpr _Tp* construct_at(_Tp* _LIBCPP_DIAGNOSE_NULLPTR __location, _Args&&... __args) { _LIBCPP_ASSERT_NON_NULL(__location != nullptr, "null pointer given to construct_at"); return ::new (static_cast(__location)) _Tp(std::forward<_Args>(__args)...); } @@ -73,13 +73,13 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_at(_Tp* __loc) { #if _LIBCPP_STD_VER >= 17 template , int> = 0> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void destroy_at(_Tp* __loc) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void destroy_at(_Tp* _LIBCPP_DIAGNOSE_NULLPTR __loc) { std::__destroy_at(__loc); } # if _LIBCPP_STD_VER >= 20 template , int> = 0> -_LIBCPP_HIDE_FROM_ABI constexpr void destroy_at(_Tp* __loc) { +_LIBCPP_HIDE_FROM_ABI constexpr void destroy_at(_Tp* _LIBCPP_DIAGNOSE_NULLPTR __loc) { std::__destroy_at(__loc); } # endif diff --git a/libcxx/include/__memory_resource/polymorphic_allocator.h b/libcxx/include/__memory_resource/polymorphic_allocator.h index 1b8711f10811d..6e7a9afc25deb 100644 --- a/libcxx/include/__memory_resource/polymorphic_allocator.h +++ b/libcxx/include/__memory_resource/polymorphic_allocator.h @@ -135,10 +135,10 @@ class _LIBCPP_AVAILABILITY_PMR polymorphic_allocator { piecewise_construct, __transform_tuple(typename __uses_alloc_ctor< _T1, polymorphic_allocator&, _Args1... >::type(), std::move(__x), - typename __make_tuple_indices::type{}), + make_index_sequence()), __transform_tuple(typename __uses_alloc_ctor< _T2, polymorphic_allocator&, _Args2... >::type(), std::move(__y), - typename __make_tuple_indices::type{})); + make_index_sequence())); } template @@ -194,20 +194,20 @@ class _LIBCPP_AVAILABILITY_PMR polymorphic_allocator { private: template _LIBCPP_HIDE_FROM_ABI tuple<_Args&&...> - __transform_tuple(integral_constant, tuple<_Args...>&& __t, __tuple_indices<_Is...>) { + __transform_tuple(integral_constant, tuple<_Args...>&& __t, index_sequence<_Is...>) { return std::forward_as_tuple(std::get<_Is>(std::move(__t))...); } template _LIBCPP_HIDE_FROM_ABI tuple - __transform_tuple(integral_constant, tuple<_Args...>&& __t, __tuple_indices<_Is...>) { + __transform_tuple(integral_constant, tuple<_Args...>&& __t, index_sequence<_Is...>) { using _Tup = tuple; return _Tup(allocator_arg, *this, std::get<_Is>(std::move(__t))...); } template _LIBCPP_HIDE_FROM_ABI tuple<_Args&&..., polymorphic_allocator&> - __transform_tuple(integral_constant, tuple<_Args...>&& __t, __tuple_indices<_Is...>) { + __transform_tuple(integral_constant, tuple<_Args...>&& __t, index_sequence<_Is...>) { using _Tup = tuple<_Args&&..., polymorphic_allocator&>; return _Tup(std::get<_Is>(std::move(__t))..., *this); } diff --git a/libcxx/include/__mutex/once_flag.h b/libcxx/include/__mutex/once_flag.h index 33064499550eb..e384c15a9f9b6 100644 --- a/libcxx/include/__mutex/once_flag.h +++ b/libcxx/include/__mutex/once_flag.h @@ -13,9 +13,9 @@ #include <__functional/invoke.h> #include <__memory/addressof.h> #include <__memory/shared_count.h> // __libcpp_acquire_load -#include <__tuple/tuple_indices.h> #include <__tuple/tuple_size.h> #include <__utility/forward.h> +#include <__utility/integer_sequence.h> #include <__utility/move.h> #include #ifndef _LIBCPP_CXX03_LANG @@ -87,15 +87,12 @@ class __call_once_param { public: _LIBCPP_HIDE_FROM_ABI explicit __call_once_param(_Fp& __f) : __f_(__f) {} - _LIBCPP_HIDE_FROM_ABI void operator()() { - typedef typename __make_tuple_indices::value, 1>::type _Index; - __execute(_Index()); - } + _LIBCPP_HIDE_FROM_ABI void operator()() { __execute(__make_index_sequence::value>()); } private: template - _LIBCPP_HIDE_FROM_ABI void __execute(__tuple_indices<_Indices...>) { - std::__invoke(std::get<0>(std::move(__f_)), std::get<_Indices>(std::move(__f_))...); + _LIBCPP_HIDE_FROM_ABI void __execute(__index_sequence<_Indices...>) { + std::__invoke(std::get<_Indices>(std::move(__f_))...); } }; diff --git a/libcxx/include/__ranges/zip_transform_view.h b/libcxx/include/__ranges/zip_transform_view.h new file mode 100644 index 0000000000000..07aa182f2858f --- /dev/null +++ b/libcxx/include/__ranges/zip_transform_view.h @@ -0,0 +1,357 @@ +// -*- 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___RANGES_ZIP_TRANSFORM_VIEW_H +#define _LIBCPP___RANGES_ZIP_TRANSFORM_VIEW_H + +#include <__config> + +#include <__concepts/constructible.h> +#include <__concepts/convertible_to.h> +#include <__concepts/derived_from.h> +#include <__concepts/equality_comparable.h> +#include <__concepts/invocable.h> +#include <__functional/invoke.h> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> +#include <__ranges/access.h> +#include <__ranges/all.h> +#include <__ranges/concepts.h> +#include <__ranges/empty_view.h> +#include <__ranges/movable_box.h> +#include <__ranges/view_interface.h> +#include <__ranges/zip_view.h> +#include <__type_traits/decay.h> +#include <__type_traits/invoke.h> +#include <__type_traits/is_object.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/is_referenceable.h> +#include <__type_traits/maybe_const.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/forward.h> +#include <__utility/in_place.h> +#include <__utility/move.h> +#include // for std::apply + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +namespace ranges { + +template + requires(view<_Views> && ...) && + (sizeof...(_Views) > 0) && is_object_v<_Fn> && regular_invocable<_Fn&, range_reference_t<_Views>...> && + __referenceable...>> +class zip_transform_view : public view_interface> { + _LIBCPP_NO_UNIQUE_ADDRESS zip_view<_Views...> __zip_; + _LIBCPP_NO_UNIQUE_ADDRESS __movable_box<_Fn> __fun_; + + using _InnerView _LIBCPP_NODEBUG = zip_view<_Views...>; + template + using __ziperator _LIBCPP_NODEBUG = iterator_t<__maybe_const<_Const, _InnerView>>; + template + using __zentinel _LIBCPP_NODEBUG = sentinel_t<__maybe_const<_Const, _InnerView>>; + + template + class __iterator; + + template + class __sentinel; + +public: + _LIBCPP_HIDE_FROM_ABI zip_transform_view() = default; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit zip_transform_view(_Fn __fun, _Views... __views) + : __zip_(std::move(__views)...), __fun_(in_place, std::move(__fun)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr auto begin() { return __iterator(*this, __zip_.begin()); } + + _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const + requires range && regular_invocable...> + { + return __iterator(*this, __zip_.begin()); + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() { + if constexpr (common_range<_InnerView>) { + return __iterator(*this, __zip_.end()); + } else { + return __sentinel(__zip_.end()); + } + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() const + requires range && regular_invocable...> + { + if constexpr (common_range) { + return __iterator(*this, __zip_.end()); + } else { + return __sentinel(__zip_.end()); + } + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto size() + requires sized_range<_InnerView> + { + return __zip_.size(); + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto size() const + requires sized_range + { + return __zip_.size(); + } +}; + +template +zip_transform_view(_Fn, _Ranges&&...) -> zip_transform_view<_Fn, views::all_t<_Ranges>...>; + +template +struct __zip_transform_iterator_category_base {}; + +template + requires forward_range<__maybe_const<_Const, zip_view<_Views...>>> +struct __zip_transform_iterator_category_base<_Const, _Fn, _Views...> { +private: + template + using __tag _LIBCPP_NODEBUG = typename iterator_traits>>::iterator_category; + + static consteval auto __get_iterator_category() { + if constexpr (!is_reference_v&, + range_reference_t<__maybe_const<_Const, _Views>>...>>) { + return input_iterator_tag(); + } else if constexpr ((derived_from<__tag<_Views>, random_access_iterator_tag> && ...)) { + return random_access_iterator_tag(); + } else if constexpr ((derived_from<__tag<_Views>, bidirectional_iterator_tag> && ...)) { + return bidirectional_iterator_tag(); + } else if constexpr ((derived_from<__tag<_Views>, forward_iterator_tag> && ...)) { + return forward_iterator_tag(); + } else { + return input_iterator_tag(); + } + } + +public: + using iterator_category = decltype(__get_iterator_category()); +}; + +template + requires(view<_Views> && ...) && + (sizeof...(_Views) > 0) && is_object_v<_Fn> && regular_invocable<_Fn&, range_reference_t<_Views>...> && + __referenceable...>> +template +class zip_transform_view<_Fn, _Views...>::__iterator + : public __zip_transform_iterator_category_base<_Const, _Fn, _Views...> { + using _Parent _LIBCPP_NODEBUG = __maybe_const<_Const, zip_transform_view>; + using _Base _LIBCPP_NODEBUG = __maybe_const<_Const, _InnerView>; + + friend zip_transform_view<_Fn, _Views...>; + + _Parent* __parent_ = nullptr; + __ziperator<_Const> __inner_; + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator(_Parent& __parent, __ziperator<_Const> __inner) + : __parent_(std::addressof(__parent)), __inner_(std::move(__inner)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr auto __get_deref_and_invoke() const noexcept { + return [&__fun = *__parent_->__fun_](const auto&... __iters) noexcept(noexcept(std::invoke( + *__parent_->__fun_, *__iters...))) -> decltype(auto) { return std::invoke(__fun, *__iters...); }; + } + +public: + using iterator_concept = typename __ziperator<_Const>::iterator_concept; + using value_type = + remove_cvref_t&, range_reference_t<__maybe_const<_Const, _Views>>...>>; + using difference_type = range_difference_t<_Base>; + + _LIBCPP_HIDE_FROM_ABI __iterator() = default; + _LIBCPP_HIDE_FROM_ABI constexpr __iterator(__iterator __i) + requires _Const && convertible_to<__ziperator, __ziperator<_Const>> + : __parent_(__i.__parent_), __inner_(std::move(__i.__inner_)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const + noexcept(noexcept(std::apply(__get_deref_and_invoke(), __zip_view_iterator_access::__get_underlying(__inner_)))) { + return std::apply(__get_deref_and_invoke(), __zip_view_iterator_access::__get_underlying(__inner_)); + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { + ++__inner_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++*this; } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) + requires forward_range<_Base> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--() + requires bidirectional_range<_Base> + { + --__inner_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int) + requires bidirectional_range<_Base> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __x) + requires random_access_range<_Base> + { + __inner_ += __x; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __x) + requires random_access_range<_Base> + { + __inner_ -= __x; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](difference_type __n) const + requires random_access_range<_Base> + { + return std::apply( + [&](const _Is&... __iters) -> decltype(auto) { + return std::invoke(*__parent_->__fun_, __iters[iter_difference_t<_Is>(__n)]...); + }, + __zip_view_iterator_access::__get_underlying(__inner_)); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) + requires equality_comparable<__ziperator<_Const>> + { + return __x.__inner_ == __y.__inner_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) + requires random_access_range<_Base> + { + return __x.__inner_ <=> __y.__inner_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(const __iterator& __i, difference_type __n) + requires random_access_range<_Base> + { + return __iterator(*__i.__parent_, __i.__inner_ + __n); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __n, const __iterator& __i) + requires random_access_range<_Base> + { + return __iterator(*__i.__parent_, __i.__inner_ + __n); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(const __iterator& __i, difference_type __n) + requires random_access_range<_Base> + { + return __iterator(*__i.__parent_, __i.__inner_ - __n); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) + requires sized_sentinel_for<__ziperator<_Const>, __ziperator<_Const>> + { + return __x.__inner_ - __y.__inner_; + } +}; + +template + requires(view<_Views> && ...) && + (sizeof...(_Views) > 0) && is_object_v<_Fn> && regular_invocable<_Fn&, range_reference_t<_Views>...> && + __referenceable...>> +template +class zip_transform_view<_Fn, _Views...>::__sentinel { + __zentinel<_Const> __inner_; + + friend zip_transform_view<_Fn, _Views...>; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(__zentinel<_Const> __inner) : __inner_(__inner) {} + +public: + _LIBCPP_HIDE_FROM_ABI __sentinel() = default; + + _LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel __i) + requires _Const && convertible_to<__zentinel, __zentinel<_Const>> + : __inner_(__i.__inner_) {} + + template + requires sentinel_for<__zentinel<_Const>, __ziperator<_OtherConst>> + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { + return __x.__inner_ == __y.__inner_; + } + + template + requires sized_sentinel_for<__zentinel<_Const>, __ziperator<_OtherConst>> + _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _InnerView>> + operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) { + return __x.__inner_ - __y.__inner_; + } + + template + requires sized_sentinel_for<__zentinel<_Const>, __ziperator<_OtherConst>> + _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _InnerView>> + operator-(const __sentinel& __x, const __iterator<_OtherConst>& __y) { + return __x.__inner_ - __y.__inner_; + } +}; + +namespace views { +namespace __zip_transform { + +struct __fn { + template + requires(move_constructible> && regular_invocable&> && + is_object_v&>>) + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Fn&&) const + noexcept(noexcept(auto(views::empty&>>>))) { + return views::empty&>>>; + } + + template + requires(sizeof...(_Ranges) > 0) + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Fn&& __fun, _Ranges&&... __rs) const + noexcept(noexcept(zip_transform_view(std::forward<_Fn>(__fun), std::forward<_Ranges>(__rs)...))) + -> decltype(zip_transform_view(std::forward<_Fn>(__fun), std::forward<_Ranges>(__rs)...)) { + return zip_transform_view(std::forward<_Fn>(__fun), std::forward<_Ranges>(__rs)...); + } +}; + +} // namespace __zip_transform +inline namespace __cpo { +inline constexpr auto zip_transform = __zip_transform::__fn{}; +} // namespace __cpo +} // namespace views +} // namespace ranges + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___RANGES_ZIP_TRANSFORM_VIEW_H diff --git a/libcxx/include/__ranges/zip_view.h b/libcxx/include/__ranges/zip_view.h index e2a194efcfb4c..ce00c98710c4e 100644 --- a/libcxx/include/__ranges/zip_view.h +++ b/libcxx/include/__ranges/zip_view.h @@ -235,6 +235,13 @@ struct __zip_view_iterator_category_base<_Const, _Views...> { using iterator_category = input_iterator_tag; }; +struct __zip_view_iterator_access { + template + _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) __get_underlying(_Iter& __iter) noexcept { + return (__iter.__current_); + } +}; + template requires(view<_Views> && ...) && (sizeof...(_Views) > 0) template @@ -255,6 +262,7 @@ class zip_view<_Views...>::__iterator : public __zip_view_iterator_category_base static constexpr bool __is_zip_view_iterator = true; friend struct __product_iterator_traits<__iterator>; + friend __zip_view_iterator_access; public: using iterator_concept = decltype(ranges::__get_zip_view_iterator_tag<_Const, _Views...>()); diff --git a/libcxx/include/__thread/thread.h b/libcxx/include/__thread/thread.h index 1b51571ce302e..a3b672bc0f0e7 100644 --- a/libcxx/include/__thread/thread.h +++ b/libcxx/include/__thread/thread.h @@ -155,8 +155,8 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) { # ifndef _LIBCPP_CXX03_LANG template -inline _LIBCPP_HIDE_FROM_ABI void __thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __tuple_indices<_Indices...>) { - std::__invoke(std::move(std::get<1>(__t)), std::move(std::get<_Indices>(__t))...); +inline _LIBCPP_HIDE_FROM_ABI void __thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __index_sequence<_Indices...>) { + std::__invoke(std::move(std::get<_Indices + 1>(__t))...); } template @@ -164,8 +164,7 @@ _LIBCPP_HIDE_FROM_ABI void* __thread_proxy(void* __vp) { // _Fp = tuple< unique_ptr<__thread_struct>, Functor, Args...> unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); __thread_local_data().set_pointer(std::get<0>(*__p.get()).release()); - typedef typename __make_tuple_indices::value, 2>::type _Index; - std::__thread_execute(*__p.get(), _Index()); + std::__thread_execute(*__p.get(), __make_index_sequence::value - 1>()); return nullptr; } diff --git a/libcxx/include/__tree b/libcxx/include/__tree index f29b691b73dda..f8bb4f01b1e29 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -855,17 +855,11 @@ public: private: _LIBCPP_HIDE_FROM_ABI const __node_allocator& __node_alloc() const _NOEXCEPT { return __node_alloc_; } - _LIBCPP_HIDE_FROM_ABI __end_node_pointer& __begin_node() _NOEXCEPT { return __begin_node_; } - _LIBCPP_HIDE_FROM_ABI const __end_node_pointer& __begin_node() const _NOEXCEPT { return __begin_node_; } public: _LIBCPP_HIDE_FROM_ABI allocator_type __alloc() const _NOEXCEPT { return allocator_type(__node_alloc()); } -private: - _LIBCPP_HIDE_FROM_ABI size_type& size() _NOEXCEPT { return __size_; } - -public: - _LIBCPP_HIDE_FROM_ABI const size_type& size() const _NOEXCEPT { return __size_; } + _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __size_; } _LIBCPP_HIDE_FROM_ABI value_compare& value_comp() _NOEXCEPT { return __value_comp_; } _LIBCPP_HIDE_FROM_ABI const value_compare& value_comp() const _NOEXCEPT { return __value_comp_; } @@ -902,8 +896,8 @@ public: _LIBCPP_HIDE_FROM_ABI ~__tree(); - _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return iterator(__begin_node()); } - _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return const_iterator(__begin_node()); } + _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return iterator(__begin_node_); } + _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return const_iterator(__begin_node_); } _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return iterator(__end_node()); } _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return const_iterator(__end_node()); } @@ -1225,30 +1219,30 @@ template __tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp) _NOEXCEPT_( is_nothrow_default_constructible<__node_allocator>::value&& is_nothrow_copy_constructible::value) : __size_(0), __value_comp_(__comp) { - __begin_node() = __end_node(); + __begin_node_ = __end_node(); } template __tree<_Tp, _Compare, _Allocator>::__tree(const allocator_type& __a) : __begin_node_(), __node_alloc_(__node_allocator(__a)), __size_(0) { - __begin_node() = __end_node(); + __begin_node_ = __end_node(); } template __tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp, const allocator_type& __a) : __begin_node_(), __node_alloc_(__node_allocator(__a)), __size_(0), __value_comp_(__comp) { - __begin_node() = __end_node(); + __begin_node_ = __end_node(); } -// Precondition: size() != 0 +// Precondition: __size_ != 0 template typename __tree<_Tp, _Compare, _Allocator>::__node_pointer __tree<_Tp, _Compare, _Allocator>::_DetachedTreeCache::__detach_from_tree(__tree* __t) _NOEXCEPT { - __node_pointer __cache = static_cast<__node_pointer>(__t->__begin_node()); - __t->__begin_node() = __t->__end_node(); + __node_pointer __cache = static_cast<__node_pointer>(__t->__begin_node_); + __t->__begin_node_ = __t->__end_node(); __t->__end_node()->__left_->__parent_ = nullptr; __t->__end_node()->__left_ = nullptr; - __t->size() = 0; + __t->__size_ = 0; // __cache->__left_ == nullptr if (__cache->__right_ != nullptr) __cache = static_cast<__node_pointer>(__cache->__right_); @@ -1300,7 +1294,7 @@ void __tree<_Tp, _Compare, _Allocator>::__assign_unique(_ForwardIterator __first is_same<_ItValueType, value_type>::value, "__assign_unique may only be called with the containers value type"); static_assert( __has_forward_iterator_category<_ForwardIterator>::value, "__assign_unique requires a forward iterator"); - if (size() != 0) { + if (__size_ != 0) { _DetachedTreeCache __cache(this); for (; __cache.__get() != nullptr && __first != __last; ++__first) { if (__node_assign_unique(*__first, __cache.__get()).second) @@ -1318,7 +1312,7 @@ void __tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _ typedef typename _ITraits::value_type _ItValueType; static_assert( is_same<_ItValueType, value_type>::value, "__assign_multi may only be called with the containers value_type"); - if (size() != 0) { + if (__size_ != 0) { _DetachedTreeCache __cache(this); for (; __cache.__get() && __first != __last; ++__first) { __assign_value(__cache.__get()->__value_, *__first); @@ -1337,7 +1331,7 @@ __tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t) __node_alloc_(__node_traits::select_on_container_copy_construction(__t.__node_alloc())), __size_(0), __value_comp_(__t.value_comp()) { - __begin_node() = __end_node(); + __begin_node_ = __end_node(); } template @@ -1348,13 +1342,13 @@ __tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t) _NOEXCEPT_( __node_alloc_(std::move(__t.__node_alloc_)), __size_(__t.__size_), __value_comp_(std::move(__t.__value_comp_)) { - if (size() == 0) - __begin_node() = __end_node(); + if (__size_ == 0) + __begin_node_ = __end_node(); else { __end_node()->__left_->__parent_ = static_cast<__end_node_pointer>(__end_node()); - __t.__begin_node() = __t.__end_node(); + __t.__begin_node_ = __t.__end_node(); __t.__end_node()->__left_ = nullptr; - __t.size() = 0; + __t.__size_ = 0; } } @@ -1362,19 +1356,19 @@ template __tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t, const allocator_type& __a) : __node_alloc_(__node_allocator(__a)), __size_(0), __value_comp_(std::move(__t.value_comp())) { if (__a == __t.__alloc()) { - if (__t.size() == 0) - __begin_node() = __end_node(); + if (__t.__size_ == 0) + __begin_node_ = __end_node(); else { - __begin_node() = __t.__begin_node(); + __begin_node_ = __t.__begin_node_; __end_node()->__left_ = __t.__end_node()->__left_; __end_node()->__left_->__parent_ = static_cast<__end_node_pointer>(__end_node()); - size() = __t.size(); - __t.__begin_node() = __t.__end_node(); + __size_ = __t.__size_; + __t.__begin_node_ = __t.__end_node(); __t.__end_node()->__left_ = nullptr; - __t.size() = 0; + __t.__size_ = 0; } } else { - __begin_node() = __end_node(); + __begin_node_ = __end_node(); } } @@ -1387,13 +1381,13 @@ void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, true_type) __move_assign_alloc(__t); __size_ = __t.__size_; __value_comp_ = std::move(__t.__value_comp_); - if (size() == 0) - __begin_node() = __end_node(); + if (__size_ == 0) + __begin_node_ = __end_node(); else { __end_node()->__left_->__parent_ = static_cast<__end_node_pointer>(__end_node()); - __t.__begin_node() = __t.__end_node(); + __t.__begin_node_ = __t.__end_node(); __t.__end_node()->__left_ = nullptr; - __t.size() = 0; + __t.__size_ = 0; } } @@ -1404,15 +1398,15 @@ void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type) { else { value_comp() = std::move(__t.value_comp()); const_iterator __e = end(); - if (size() != 0) { + if (__size_ != 0) { _DetachedTreeCache __cache(this); - while (__cache.__get() != nullptr && __t.size() != 0) { + while (__cache.__get() != nullptr && __t.__size_ != 0) { __assign_value(__cache.__get()->__value_, std::move(__t.remove(__t.begin())->__value_)); __node_insert_multi(__cache.__get()); __cache.__advance(); } } - while (__t.size() != 0) { + while (__t.__size_ != 0) { __insert_multi_from_orphaned_node(__e, std::move(__t.remove(__t.begin())->__value_)); } } @@ -1460,12 +1454,12 @@ void __tree<_Tp, _Compare, _Allocator>::swap(__tree& __t) std::__swap_allocator(__node_alloc(), __t.__node_alloc()); swap(__size_, __t.__size_); swap(__value_comp_, __t.__value_comp_); - if (size() == 0) - __begin_node() = __end_node(); + if (__size_ == 0) + __begin_node_ = __end_node(); else __end_node()->__left_->__parent_ = __end_node(); - if (__t.size() == 0) - __t.__begin_node() = __t.__end_node(); + if (__t.__size_ == 0) + __t.__begin_node_ = __t.__end_node(); else __t.__end_node()->__left_->__parent_ = __t.__end_node(); } @@ -1473,8 +1467,8 @@ void __tree<_Tp, _Compare, _Allocator>::swap(__tree& __t) template void __tree<_Tp, _Compare, _Allocator>::clear() _NOEXCEPT { destroy(__root()); - size() = 0; - __begin_node() = __end_node(); + __size_ = 0; + __begin_node_ = __end_node(); __end_node()->__left_ = nullptr; } @@ -1664,10 +1658,10 @@ void __tree<_Tp, _Compare, _Allocator>::__insert_node_at( __new_node->__parent_ = __parent; // __new_node->__is_black_ is initialized in __tree_balance_after_insert __child = __new_node; - if (__begin_node()->__left_ != nullptr) - __begin_node() = static_cast<__end_node_pointer>(__begin_node()->__left_); + if (__begin_node_->__left_ != nullptr) + __begin_node_ = static_cast<__end_node_pointer>(__begin_node_->__left_); std::__tree_balance_after_insert(__end_node()->__left_, __child); - ++size(); + ++__size_; } template @@ -1811,9 +1805,9 @@ typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__remove_node_pointer(__node_pointer __ptr) _NOEXCEPT { iterator __r(__ptr); ++__r; - if (__begin_node() == __ptr) - __begin_node() = __r.__ptr_; - --size(); + if (__begin_node_ == __ptr) + __begin_node_ = __r.__ptr_; + --__size_; std::__tree_remove(__end_node()->__left_, static_cast<__node_base_pointer>(__ptr)); return __r; } @@ -2177,13 +2171,13 @@ template typename __tree<_Tp, _Compare, _Allocator>::__node_holder __tree<_Tp, _Compare, _Allocator>::remove(const_iterator __p) _NOEXCEPT { __node_pointer __np = __p.__get_np(); - if (__begin_node() == __p.__ptr_) { + if (__begin_node_ == __p.__ptr_) { if (__np->__right_ != nullptr) - __begin_node() = static_cast<__end_node_pointer>(__np->__right_); + __begin_node_ = static_cast<__end_node_pointer>(__np->__right_); else - __begin_node() = static_cast<__end_node_pointer>(__np->__parent_); + __begin_node_ = static_cast<__end_node_pointer>(__np->__parent_); } - --size(); + --__size_; std::__tree_remove(__end_node()->__left_, static_cast<__node_base_pointer>(__np)); return __node_holder(__np, _Dp(__node_alloc(), true)); } diff --git a/libcxx/include/__tuple/make_tuple_types.h b/libcxx/include/__tuple/make_tuple_types.h index a5c9bcf23a6eb..3c22ec85dc9c7 100644 --- a/libcxx/include/__tuple/make_tuple_types.h +++ b/libcxx/include/__tuple/make_tuple_types.h @@ -14,12 +14,12 @@ #include <__fwd/array.h> #include <__fwd/tuple.h> #include <__tuple/tuple_element.h> -#include <__tuple/tuple_indices.h> #include <__tuple/tuple_size.h> #include <__tuple/tuple_types.h> #include <__type_traits/copy_cvref.h> #include <__type_traits/remove_cvref.h> #include <__type_traits/remove_reference.h> +#include <__utility/integer_sequence.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -38,38 +38,35 @@ template struct __make_tuple_types_flat; template